From 94b2861243907eb952162764842276250e3f20fe Mon Sep 17 00:00:00 2001 From: "Xamarin Public Jenkins (auto-signing)" Date: Thu, 10 Nov 2016 13:04:39 +0000 Subject: [PATCH] Imported Upstream version 4.8.0.309 Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850 --- Makefile.am | 24 +- Makefile.in | 30 +- acceptance-tests/Makefile.am | 4 +- acceptance-tests/Makefile.in.REMOVED.git-id | 2 +- acceptance-tests/SUBMODULES.json | 12 +- acceptance-tests/coreclr.mk.REMOVED.git-id | 2 +- acceptance-tests/ms-test-suite.mk | 4 +- acceptance-tests/profiler-stress.mk | 13 + acceptance-tests/roslyn.mk | 8 +- acceptance-tests/versions.mk | 10 + autogen.sh | 5 +- config.h.in | 9 +- configure.REMOVED.git-id | 2 +- configure.ac.REMOVED.git-id | 2 +- data/Makefile.in | 13 +- data/config.in | 1 + data/net_2_0/Browsers/Makefile.in | 13 +- data/net_2_0/Makefile.in | 13 +- data/net_4_0/Browsers/Makefile.in | 13 +- data/net_4_0/Makefile.in | 13 +- data/net_4_5/Browsers/Makefile.in | 13 +- data/net_4_5/Makefile.in | 13 +- docs/Makefile.in | 13 +- docs/deploy/mono-api-gc.html | 7 +- docs/deploy/mono-api-internal.html | 9 +- docs/deploy/mono-api-unsorted.html | 2 +- docs/deploy/mono-api-wapi.html.REMOVED.git-id | 2 +- docs/sources/mono-api-gc.html | 7 +- eglib/config.h.in | 3 + eglib/configure.REMOVED.git-id | 2 +- eglib/configure.ac | 11 +- eglib/src/Makefile.am | 12 +- eglib/src/Makefile.in | 37 +- eglib/src/gerror.c | 10 +- eglib/src/gfile-win32.c | 21 + eglib/src/giconv.c | 5 +- eglib/src/glib.h | 17 +- eglib/src/gmarkup.c | 2 +- eglib/src/gmem.c | 60 +- eglib/src/gmisc-win32.c | 42 +- eglib/src/goutput.c | 14 +- eglib/src/gstr.c | 43 +- eglib/src/vasprintf.c | 31 - eglib/src/vasprintf.h | 11 - eglib/test/test.c | 9 +- external/boringssl/.clang-format | 7 + .../boringssl/.github/PULL_REQUEST_TEMPLATE | 7 + external/boringssl/.gitignore | 6 + external/boringssl/BUILDING.md | 145 + external/boringssl/CMakeLists.txt | 232 + external/boringssl/CONTRIBUTING.md | 49 + external/boringssl/FUZZING.md | 63 + external/boringssl/INCORPORATING.md | 90 + external/boringssl/LICENSE | 192 + external/boringssl/PORTING.md | 187 + external/boringssl/README.md | 32 + external/boringssl/STYLE.md | 197 + external/boringssl/codereview.settings | 4 + external/boringssl/crypto/CMakeLists.txt | 277 + external/boringssl/crypto/aes/CMakeLists.txt | 74 + external/boringssl/crypto/aes/aes.c | 1142 ++++ external/boringssl/crypto/aes/aes_test.cc | 102 + .../crypto/aes/asm/aes-586.pl.REMOVED.git-id | 1 + .../boringssl/crypto/aes/asm/aes-armv4.pl | 1244 +++++ .../boringssl/crypto/aes/asm/aes-x86_64.pl | 2805 ++++++++++ .../boringssl/crypto/aes/asm/aesni-x86.pl | 2525 +++++++++ .../aes/asm/aesni-x86_64.pl.REMOVED.git-id | 1 + .../boringssl/crypto/aes/asm/aesv8-armx.pl | 1001 ++++ .../boringssl/crypto/aes/asm/bsaes-armv7.pl | 2505 +++++++++ .../boringssl/crypto/aes/asm/bsaes-x86_64.pl | 3102 +++++++++++ .../boringssl/crypto/aes/asm/vpaes-x86.pl | 903 +++ .../boringssl/crypto/aes/asm/vpaes-x86_64.pl | 1207 ++++ external/boringssl/crypto/aes/internal.h | 87 + external/boringssl/crypto/aes/mode_wrappers.c | 112 + external/boringssl/crypto/asn1/CMakeLists.txt | 54 + external/boringssl/crypto/asn1/a_bitstr.c | 263 + external/boringssl/crypto/asn1/a_bool.c | 110 + external/boringssl/crypto/asn1/a_bytes.c | 308 ++ external/boringssl/crypto/asn1/a_d2i_fp.c | 282 + external/boringssl/crypto/asn1/a_dup.c | 111 + external/boringssl/crypto/asn1/a_enum.c | 181 + external/boringssl/crypto/asn1/a_gentm.c | 256 + external/boringssl/crypto/asn1/a_i2d_fp.c | 147 + external/boringssl/crypto/asn1/a_int.c | 460 ++ external/boringssl/crypto/asn1/a_mbstr.c | 409 ++ external/boringssl/crypto/asn1/a_object.c | 396 ++ external/boringssl/crypto/asn1/a_octet.c | 77 + external/boringssl/crypto/asn1/a_print.c | 121 + external/boringssl/crypto/asn1/a_strnid.c | 309 ++ external/boringssl/crypto/asn1/a_time.c | 217 + external/boringssl/crypto/asn1/a_type.c | 151 + external/boringssl/crypto/asn1/a_utctm.c | 335 ++ external/boringssl/crypto/asn1/a_utf8.c | 234 + external/boringssl/crypto/asn1/asn1_lib.c | 505 ++ external/boringssl/crypto/asn1/asn1_locl.h | 63 + external/boringssl/crypto/asn1/asn1_par.c | 80 + external/boringssl/crypto/asn1/asn1_test.cc | 81 + external/boringssl/crypto/asn1/asn_pack.c | 105 + external/boringssl/crypto/asn1/charmap.pl | 135 + external/boringssl/crypto/asn1/f_enum.c | 200 + external/boringssl/crypto/asn1/f_int.c | 202 + external/boringssl/crypto/asn1/f_string.c | 196 + external/boringssl/crypto/asn1/t_bitst.c | 103 + external/boringssl/crypto/asn1/tasn_dec.c | 1219 +++++ external/boringssl/crypto/asn1/tasn_enc.c | 657 +++ external/boringssl/crypto/asn1/tasn_fre.c | 246 + external/boringssl/crypto/asn1/tasn_new.c | 381 ++ external/boringssl/crypto/asn1/tasn_typ.c | 144 + external/boringssl/crypto/asn1/tasn_utl.c | 266 + external/boringssl/crypto/asn1/x_bignum.c | 153 + external/boringssl/crypto/asn1/x_long.c | 197 + .../boringssl/crypto/base64/CMakeLists.txt | 22 + external/boringssl/crypto/base64/base64.c | 438 ++ .../boringssl/crypto/base64/base64_test.cc | 393 ++ external/boringssl/crypto/bio/CMakeLists.txt | 35 + external/boringssl/crypto/bio/bio.c | 608 ++ external/boringssl/crypto/bio/bio_mem.c | 328 ++ external/boringssl/crypto/bio/bio_test.cc | 440 ++ external/boringssl/crypto/bio/buffer.c | 496 ++ external/boringssl/crypto/bio/connect.c | 553 ++ external/boringssl/crypto/bio/fd.c | 277 + external/boringssl/crypto/bio/file.c | 313 ++ external/boringssl/crypto/bio/hexdump.c | 192 + external/boringssl/crypto/bio/internal.h | 111 + external/boringssl/crypto/bio/pair.c | 803 +++ external/boringssl/crypto/bio/printf.c | 119 + external/boringssl/crypto/bio/socket.c | 203 + external/boringssl/crypto/bio/socket_helper.c | 113 + external/boringssl/crypto/bn/CMakeLists.txt | 90 + external/boringssl/crypto/bn/add.c | 377 ++ .../boringssl/crypto/bn/asm/armv4-mont.pl | 693 +++ .../boringssl/crypto/bn/asm/armv8-mont.pl | 1503 +++++ external/boringssl/crypto/bn/asm/bn-586.pl | 774 +++ external/boringssl/crypto/bn/asm/co-586.pl | 287 + external/boringssl/crypto/bn/asm/rsaz-avx2.pl | 1945 +++++++ .../boringssl/crypto/bn/asm/rsaz-x86_64.pl | 2338 ++++++++ external/boringssl/crypto/bn/asm/x86-mont.pl | 592 ++ external/boringssl/crypto/bn/asm/x86_64-gcc.c | 531 ++ .../boringssl/crypto/bn/asm/x86_64-mont.pl | 1430 +++++ .../boringssl/crypto/bn/asm/x86_64-mont5.pl | 3669 +++++++++++++ external/boringssl/crypto/bn/bn.c | 353 ++ external/boringssl/crypto/bn/bn_asn1.c | 80 + external/boringssl/crypto/bn/bn_test.cc | 1943 +++++++ external/boringssl/crypto/bn/cmp.c | 214 + external/boringssl/crypto/bn/convert.c | 607 ++ external/boringssl/crypto/bn/ctx.c | 311 ++ external/boringssl/crypto/bn/div.c | 671 +++ external/boringssl/crypto/bn/exponentiation.c | 1258 +++++ external/boringssl/crypto/bn/gcd.c | 712 +++ external/boringssl/crypto/bn/generic.c | 703 +++ external/boringssl/crypto/bn/internal.h | 237 + external/boringssl/crypto/bn/kronecker.c | 175 + external/boringssl/crypto/bn/montgomery.c | 480 ++ external/boringssl/crypto/bn/mul.c | 869 +++ external/boringssl/crypto/bn/prime.c | 845 +++ external/boringssl/crypto/bn/random.c | 326 ++ external/boringssl/crypto/bn/rsaz_exp.c | 319 ++ external/boringssl/crypto/bn/rsaz_exp.h | 56 + external/boringssl/crypto/bn/shift.c | 299 + external/boringssl/crypto/bn/sqrt.c | 505 ++ external/boringssl/crypto/buf/CMakeLists.txt | 9 + external/boringssl/crypto/buf/buf.c | 239 + .../crypto/bytestring/CMakeLists.txt | 25 + .../boringssl/crypto/bytestring/asn1_compat.c | 51 + external/boringssl/crypto/bytestring/ber.c | 263 + .../crypto/bytestring/bytestring_test.cc | 825 +++ external/boringssl/crypto/bytestring/cbb.c | 445 ++ external/boringssl/crypto/bytestring/cbs.c | 440 ++ .../boringssl/crypto/bytestring/internal.h | 75 + .../boringssl/crypto/chacha/CMakeLists.txt | 60 + .../crypto/chacha/asm/chacha-armv4.pl | 1151 ++++ .../crypto/chacha/asm/chacha-armv8.pl | 1127 ++++ .../boringssl/crypto/chacha/asm/chacha-x86.pl | 753 +++ .../crypto/chacha/asm/chacha-x86_64.pl | 1767 ++++++ external/boringssl/crypto/chacha/chacha.c | 170 + .../boringssl/crypto/chacha/chacha_test.cc | 248 + .../boringssl/crypto/cipher/CMakeLists.txt | 42 + external/boringssl/crypto/cipher/aead.c | 162 + external/boringssl/crypto/cipher/aead_test.cc | 362 ++ external/boringssl/crypto/cipher/cipher.c | 652 +++ .../boringssl/crypto/cipher/cipher_test.cc | 296 + external/boringssl/crypto/cipher/derive_key.c | 154 + external/boringssl/crypto/cipher/e_aes.c | 1715 ++++++ .../crypto/cipher/e_chacha20poly1305.c | 302 + external/boringssl/crypto/cipher/e_des.c | 207 + external/boringssl/crypto/cipher/e_null.c | 85 + external/boringssl/crypto/cipher/e_rc2.c | 443 ++ external/boringssl/crypto/cipher/e_rc4.c | 87 + external/boringssl/crypto/cipher/e_ssl3.c | 463 ++ external/boringssl/crypto/cipher/e_tls.c | 673 +++ external/boringssl/crypto/cipher/internal.h | 164 + ...128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id | 1 + ...1_tls_implicit_iv_tests.txt.REMOVED.git-id | 1 + ..._128_cbc_sha1_tls_tests.txt.REMOVED.git-id | 1 + ...28_cbc_sha256_tls_tests.txt.REMOVED.git-id | 1 + .../cipher/test/aes_128_ctr_hmac_sha256.txt | 336 ++ .../crypto/cipher/test/aes_128_gcm_tests.txt | 531 ++ .../cipher/test/aes_128_key_wrap_tests.txt | 9 + ...256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id | 1 + ...1_tls_implicit_iv_tests.txt.REMOVED.git-id | 1 + ..._256_cbc_sha1_tls_tests.txt.REMOVED.git-id | 1 + ...56_cbc_sha256_tls_tests.txt.REMOVED.git-id | 1 + ...56_cbc_sha384_tls_tests.txt.REMOVED.git-id | 1 + .../cipher/test/aes_256_ctr_hmac_sha256.txt | 336 ++ .../crypto/cipher/test/aes_256_gcm_tests.txt | 466 ++ .../cipher/test/aes_256_key_wrap_tests.txt | 23 + .../test/chacha20_poly1305_old_tests.txt | 524 ++ .../cipher/test/chacha20_poly1305_tests.txt | 578 ++ .../crypto/cipher/test/cipher_tests.txt | 613 +++ ...de3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id | 1 + ...1_tls_implicit_iv_tests.txt.REMOVED.git-id | 1 + ...ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id | 1 + .../cipher/test/make_all_legacy_aead_tests.sh | 24 + .../cipher/test/make_legacy_aead_tests.go | 357 ++ .../rc4_md5_ssl3_tests.txt.REMOVED.git-id | 1 + .../test/rc4_md5_tls_tests.txt.REMOVED.git-id | 1 + .../rc4_sha1_ssl3_tests.txt.REMOVED.git-id | 1 + .../rc4_sha1_tls_tests.txt.REMOVED.git-id | 1 + external/boringssl/crypto/cipher/tls_cbc.c | 564 ++ external/boringssl/crypto/cmac/CMakeLists.txt | 22 + external/boringssl/crypto/cmac/cmac.c | 239 + external/boringssl/crypto/cmac/cmac_test.cc | 151 + external/boringssl/crypto/conf/CMakeLists.txt | 9 + external/boringssl/crypto/conf/conf.c | 788 +++ external/boringssl/crypto/conf/conf_def.h | 127 + external/boringssl/crypto/conf/internal.h | 31 + .../boringssl/crypto/constant_time_test.c | 307 ++ external/boringssl/crypto/cpu-aarch64-linux.c | 61 + external/boringssl/crypto/cpu-arm-linux.c | 360 ++ external/boringssl/crypto/cpu-arm.c | 38 + external/boringssl/crypto/cpu-intel.c | 263 + external/boringssl/crypto/crypto.c | 158 + .../crypto/curve25519/CMakeLists.txt | 59 + .../crypto/curve25519/asm/x25519-asm-arm.S | 2124 +++++++ .../crypto/curve25519/asm/x25519-asm-x86_64.S | 1937 +++++++ .../curve25519/curve25519.c.REMOVED.git-id | 1 + .../crypto/curve25519/ed25519_test.cc | 63 + .../ed25519_tests.txt.REMOVED.git-id | 1 + .../boringssl/crypto/curve25519/internal.h | 109 + .../boringssl/crypto/curve25519/spake25519.c | 464 ++ .../crypto/curve25519/spake25519_test.cc | 169 + .../crypto/curve25519/x25519-x86_64.c | 246 + .../crypto/curve25519/x25519_test.cc | 126 + external/boringssl/crypto/des/CMakeLists.txt | 9 + external/boringssl/crypto/des/des.c | 771 +++ external/boringssl/crypto/des/internal.h | 212 + external/boringssl/crypto/dh/CMakeLists.txt | 25 + external/boringssl/crypto/dh/check.c | 202 + external/boringssl/crypto/dh/dh.c | 460 ++ external/boringssl/crypto/dh/dh_asn1.c | 160 + external/boringssl/crypto/dh/dh_test.cc | 626 +++ external/boringssl/crypto/dh/internal.h | 80 + external/boringssl/crypto/dh/params.c | 301 + .../boringssl/crypto/digest/CMakeLists.txt | 23 + external/boringssl/crypto/digest/digest.c | 248 + .../boringssl/crypto/digest/digest_test.cc | 262 + external/boringssl/crypto/digest/digests.c | 321 ++ external/boringssl/crypto/digest/internal.h | 112 + .../boringssl/crypto/digest/md32_common.h | 262 + external/boringssl/crypto/dsa/CMakeLists.txt | 23 + external/boringssl/crypto/dsa/dsa.c | 933 ++++ external/boringssl/crypto/dsa/dsa_asn1.c | 339 ++ external/boringssl/crypto/dsa/dsa_test.c | 323 ++ external/boringssl/crypto/ec/CMakeLists.txt | 53 + .../crypto/ec/asm/p256-x86_64-asm.pl | 2734 +++++++++ external/boringssl/crypto/ec/ec.c | 935 ++++ external/boringssl/crypto/ec/ec_asn1.c | 549 ++ external/boringssl/crypto/ec/ec_key.c | 489 ++ external/boringssl/crypto/ec/ec_montgomery.c | 323 ++ external/boringssl/crypto/ec/ec_test.cc | 520 ++ external/boringssl/crypto/ec/example_mul.c | 133 + external/boringssl/crypto/ec/internal.h | 288 + external/boringssl/crypto/ec/oct.c | 428 ++ external/boringssl/crypto/ec/p224-64.c | 1198 ++++ external/boringssl/crypto/ec/p256-64.c | 1753 ++++++ .../ec/p256-x86_64-table.h.REMOVED.git-id | 1 + external/boringssl/crypto/ec/p256-x86_64.c | 573 ++ external/boringssl/crypto/ec/simple.c | 1112 ++++ external/boringssl/crypto/ec/util-64.c | 109 + external/boringssl/crypto/ec/wnaf.c | 449 ++ external/boringssl/crypto/ecdh/CMakeLists.txt | 9 + external/boringssl/crypto/ecdh/ecdh.c | 153 + .../boringssl/crypto/ecdsa/CMakeLists.txt | 24 + external/boringssl/crypto/ecdsa/ecdsa.c | 487 ++ external/boringssl/crypto/ecdsa/ecdsa_asn1.c | 227 + external/boringssl/crypto/ecdsa/ecdsa_test.cc | 363 ++ .../boringssl/crypto/engine/CMakeLists.txt | 9 + external/boringssl/crypto/engine/engine.c | 96 + external/boringssl/crypto/err/CMakeLists.txt | 52 + external/boringssl/crypto/err/asn1.errordata | 92 + external/boringssl/crypto/err/bio.errordata | 17 + external/boringssl/crypto/err/bn.errordata | 19 + .../boringssl/crypto/err/cipher.errordata | 25 + external/boringssl/crypto/err/conf.errordata | 6 + external/boringssl/crypto/err/dh.errordata | 6 + .../boringssl/crypto/err/digest.errordata | 1 + external/boringssl/crypto/err/dsa.errordata | 7 + external/boringssl/crypto/err/ec.errordata | 31 + external/boringssl/crypto/err/ecdh.errordata | 3 + external/boringssl/crypto/err/ecdsa.errordata | 6 + .../boringssl/crypto/err/engine.errordata | 1 + external/boringssl/crypto/err/err.c | 756 +++ external/boringssl/crypto/err/err_data.c | 1258 +++++ .../boringssl/crypto/err/err_data_generate.go | 284 + external/boringssl/crypto/err/err_test.cc | 162 + external/boringssl/crypto/err/evp.errordata | 30 + external/boringssl/crypto/err/hkdf.errordata | 1 + external/boringssl/crypto/err/obj.errordata | 1 + external/boringssl/crypto/err/pem.errordata | 15 + external/boringssl/crypto/err/pkcs8.errordata | 25 + external/boringssl/crypto/err/rsa.errordata | 46 + external/boringssl/crypto/err/ssl.errordata | 181 + external/boringssl/crypto/err/x509.errordata | 36 + .../boringssl/crypto/err/x509v3.errordata | 63 + external/boringssl/crypto/evp/CMakeLists.txt | 52 + external/boringssl/crypto/evp/digestsign.c | 159 + external/boringssl/crypto/evp/evp.c | 365 ++ external/boringssl/crypto/evp/evp_asn1.c | 336 ++ external/boringssl/crypto/evp/evp_ctx.c | 445 ++ .../boringssl/crypto/evp/evp_extra_test.cc | 721 +++ external/boringssl/crypto/evp/evp_test.cc | 265 + external/boringssl/crypto/evp/evp_tests.txt | 215 + external/boringssl/crypto/evp/internal.h | 237 + external/boringssl/crypto/evp/p_dsa_asn1.c | 268 + external/boringssl/crypto/evp/p_ec.c | 236 + external/boringssl/crypto/evp/p_ec_asn1.c | 257 + external/boringssl/crypto/evp/p_rsa.c | 673 +++ external/boringssl/crypto/evp/p_rsa_asn1.c | 200 + external/boringssl/crypto/evp/pbkdf.c | 151 + external/boringssl/crypto/evp/pbkdf_test.cc | 220 + external/boringssl/crypto/evp/print.c | 527 ++ external/boringssl/crypto/evp/sign.c | 151 + external/boringssl/crypto/ex_data.c | 294 + external/boringssl/crypto/hkdf/CMakeLists.txt | 22 + external/boringssl/crypto/hkdf/hkdf.c | 110 + external/boringssl/crypto/hkdf/hkdf_test.c | 296 + external/boringssl/crypto/hmac/CMakeLists.txt | 23 + external/boringssl/crypto/hmac/hmac.c | 214 + external/boringssl/crypto/hmac/hmac_test.cc | 164 + external/boringssl/crypto/hmac/hmac_tests.txt | 120 + external/boringssl/crypto/internal.h | 531 ++ .../boringssl/crypto/lhash/CMakeLists.txt | 22 + external/boringssl/crypto/lhash/lhash.c | 346 ++ external/boringssl/crypto/lhash/lhash_test.c | 203 + .../boringssl/crypto/lhash/make_macros.sh | 67 + external/boringssl/crypto/md4/CMakeLists.txt | 9 + external/boringssl/crypto/md4/md4.c | 234 + external/boringssl/crypto/md5/CMakeLists.txt | 30 + external/boringssl/crypto/md5/asm/md5-586.pl | 307 ++ .../boringssl/crypto/md5/asm/md5-x86_64.pl | 370 ++ external/boringssl/crypto/md5/md5.c | 275 + external/boringssl/crypto/mem.c | 209 + .../boringssl/crypto/modes/CMakeLists.txt | 68 + .../crypto/modes/asm/aesni-gcm-x86_64.pl | 1087 ++++ .../boringssl/crypto/modes/asm/ghash-armv4.pl | 512 ++ .../boringssl/crypto/modes/asm/ghash-x86.pl | 1393 +++++ .../crypto/modes/asm/ghash-x86_64.pl | 1742 ++++++ .../crypto/modes/asm/ghashv8-armx.pl | 422 ++ external/boringssl/crypto/modes/cbc.c | 216 + external/boringssl/crypto/modes/cfb.c | 230 + external/boringssl/crypto/modes/ctr.c | 219 + external/boringssl/crypto/modes/gcm.c | 1272 +++++ external/boringssl/crypto/modes/gcm_test.c | 411 ++ external/boringssl/crypto/modes/internal.h | 358 ++ external/boringssl/crypto/modes/ofb.c | 106 + .../boringssl/crypto/newhope/CMakeLists.txt | 42 + .../crypto/newhope/error_correction.c | 131 + external/boringssl/crypto/newhope/internal.h | 71 + external/boringssl/crypto/newhope/newhope.c | 174 + .../newhope/newhope_statistical_test.cc | 156 + .../boringssl/crypto/newhope/newhope_test.cc | 142 + .../newhope/newhope_tests.txt.REMOVED.git-id | 1 + .../crypto/newhope/newhope_vectors_test.cc | 122 + external/boringssl/crypto/newhope/ntt.c | 148 + external/boringssl/crypto/newhope/poly.c | 189 + external/boringssl/crypto/newhope/precomp.c | 306 ++ external/boringssl/crypto/newhope/reduce.c | 42 + external/boringssl/crypto/obj/CMakeLists.txt | 23 + external/boringssl/crypto/obj/README | 37 + external/boringssl/crypto/obj/obj.c | 664 +++ .../crypto/obj/obj_dat.h.REMOVED.git-id | 1 + external/boringssl/crypto/obj/obj_dat.pl | 309 ++ external/boringssl/crypto/obj/obj_mac.num | 949 ++++ external/boringssl/crypto/obj/obj_test.cc | 106 + external/boringssl/crypto/obj/obj_xref.c | 124 + external/boringssl/crypto/obj/obj_xref.h | 96 + external/boringssl/crypto/obj/obj_xref.pl | 118 + external/boringssl/crypto/obj/obj_xref.txt | 58 + external/boringssl/crypto/obj/objects.pl | 255 + external/boringssl/crypto/obj/objects.txt | 1338 +++++ external/boringssl/crypto/pem/CMakeLists.txt | 16 + external/boringssl/crypto/pem/pem_all.c | 262 + external/boringssl/crypto/pem/pem_info.c | 381 ++ external/boringssl/crypto/pem/pem_lib.c | 778 +++ external/boringssl/crypto/pem/pem_oth.c | 88 + external/boringssl/crypto/pem/pem_pk8.c | 257 + external/boringssl/crypto/pem/pem_pkey.c | 227 + external/boringssl/crypto/pem/pem_x509.c | 65 + external/boringssl/crypto/pem/pem_xaux.c | 67 + .../boringssl/crypto/perlasm/arm-xlate.pl | 172 + external/boringssl/crypto/perlasm/cbc.pl | 349 ++ external/boringssl/crypto/perlasm/readme | 124 + .../boringssl/crypto/perlasm/x86_64-xlate.pl | 1167 ++++ external/boringssl/crypto/perlasm/x86asm.pl | 292 + external/boringssl/crypto/perlasm/x86gas.pl | 263 + external/boringssl/crypto/perlasm/x86masm.pl | 200 + external/boringssl/crypto/perlasm/x86nasm.pl | 187 + .../boringssl/crypto/pkcs8/CMakeLists.txt | 32 + external/boringssl/crypto/pkcs8/internal.h | 83 + external/boringssl/crypto/pkcs8/p5_pbe.c | 151 + external/boringssl/crypto/pkcs8/p5_pbev2.c | 441 ++ external/boringssl/crypto/pkcs8/p8_pkey.c | 85 + .../boringssl/crypto/pkcs8/pkcs12_test.cc | 770 +++ external/boringssl/crypto/pkcs8/pkcs8.c | 1227 +++++ external/boringssl/crypto/pkcs8/pkcs8_test.cc | 91 + .../boringssl/crypto/poly1305/CMakeLists.txt | 33 + .../crypto/poly1305/asm/poly1305-armv4.pl | 1216 ++++ .../crypto/poly1305/asm/poly1305-armv8.pl | 925 ++++ .../crypto/poly1305/asm/poly1305-x86.pl | 1788 ++++++ .../crypto/poly1305/asm/poly1305-x86_64.pl | 2235 ++++++++ external/boringssl/crypto/poly1305/internal.h | 40 + external/boringssl/crypto/poly1305/poly1305.c | 324 ++ .../boringssl/crypto/poly1305/poly1305_arm.c | 304 + .../crypto/poly1305/poly1305_arm_asm.S | 2015 +++++++ .../crypto/poly1305/poly1305_test.cc | 131 + .../crypto/poly1305/poly1305_tests.txt | 159 + .../boringssl/crypto/poly1305/poly1305_vec.c | 890 +++ external/boringssl/crypto/rand/CMakeLists.txt | 24 + .../crypto/rand/asm/rdrand-x86_64.pl | 75 + .../boringssl/crypto/rand/deterministic.c | 49 + external/boringssl/crypto/rand/internal.h | 32 + external/boringssl/crypto/rand/rand.c | 242 + external/boringssl/crypto/rand/urandom.c | 223 + external/boringssl/crypto/rand/windows.c | 56 + external/boringssl/crypto/rc4/CMakeLists.txt | 29 + external/boringssl/crypto/rc4/asm/rc4-586.pl | 388 ++ .../boringssl/crypto/rc4/asm/rc4-x86_64.pl | 653 +++ external/boringssl/crypto/rc4/rc4.c | 283 + external/boringssl/crypto/refcount_c11.c | 67 + external/boringssl/crypto/refcount_lock.c | 53 + external/boringssl/crypto/refcount_test.c | 59 + external/boringssl/crypto/rsa/CMakeLists.txt | 26 + external/boringssl/crypto/rsa/blinding.c | 267 + external/boringssl/crypto/rsa/internal.h | 148 + external/boringssl/crypto/rsa/padding.c | 706 +++ external/boringssl/crypto/rsa/rsa.c | 794 +++ external/boringssl/crypto/rsa/rsa_asn1.c | 445 ++ external/boringssl/crypto/rsa/rsa_impl.c | 1140 ++++ external/boringssl/crypto/rsa/rsa_test.cc | 954 ++++ external/boringssl/crypto/sha/CMakeLists.txt | 66 + external/boringssl/crypto/sha/asm/sha1-586.pl | 1471 +++++ .../crypto/sha/asm/sha1-armv4-large.pl | 701 +++ .../boringssl/crypto/sha/asm/sha1-armv8.pl | 347 ++ .../boringssl/crypto/sha/asm/sha1-x86_64.pl | 2059 +++++++ .../boringssl/crypto/sha/asm/sha256-586.pl | 1275 +++++ .../boringssl/crypto/sha/asm/sha256-armv4.pl | 735 +++ .../boringssl/crypto/sha/asm/sha512-586.pl | 911 +++ .../boringssl/crypto/sha/asm/sha512-armv4.pl | 666 +++ .../boringssl/crypto/sha/asm/sha512-armv8.pl | 436 ++ .../boringssl/crypto/sha/asm/sha512-x86_64.pl | 2390 ++++++++ external/boringssl/crypto/sha/sha1.c | 337 ++ external/boringssl/crypto/sha/sha256.c | 327 ++ external/boringssl/crypto/sha/sha512.c | 607 ++ .../boringssl/crypto/stack/CMakeLists.txt | 9 + .../boringssl/crypto/stack/make_macros.sh | 114 + external/boringssl/crypto/stack/stack.c | 386 ++ external/boringssl/crypto/test/CMakeLists.txt | 9 + external/boringssl/crypto/test/file_test.cc | 302 + external/boringssl/crypto/test/file_test.h | 157 + external/boringssl/crypto/test/malloc.cc | 150 + external/boringssl/crypto/test/scoped_types.h | 145 + external/boringssl/crypto/test/test_util.cc | 30 + external/boringssl/crypto/test/test_util.h | 35 + external/boringssl/crypto/thread.c | 122 + external/boringssl/crypto/thread_none.c | 59 + external/boringssl/crypto/thread_pthread.c | 176 + external/boringssl/crypto/thread_test.c | 217 + external/boringssl/crypto/thread_win.c | 237 + external/boringssl/crypto/time_support.c | 206 + external/boringssl/crypto/x509/CMakeLists.txt | 81 + external/boringssl/crypto/x509/a_digest.c | 96 + external/boringssl/crypto/x509/a_sign.c | 135 + external/boringssl/crypto/x509/a_strex.c | 633 +++ external/boringssl/crypto/x509/a_verify.c | 127 + external/boringssl/crypto/x509/algorithm.c | 137 + external/boringssl/crypto/x509/asn1_gen.c | 818 +++ external/boringssl/crypto/x509/by_dir.c | 453 ++ external/boringssl/crypto/x509/by_file.c | 275 + external/boringssl/crypto/x509/charmap.h | 15 + external/boringssl/crypto/x509/i2d_pr.c | 83 + external/boringssl/crypto/x509/internal.h | 66 + external/boringssl/crypto/x509/pkcs7.c | 353 ++ external/boringssl/crypto/x509/pkcs7_test.c | 656 +++ external/boringssl/crypto/x509/rsa_pss.c | 385 ++ external/boringssl/crypto/x509/t_crl.c | 128 + external/boringssl/crypto/x509/t_req.c | 246 + external/boringssl/crypto/x509/t_x509.c | 506 ++ external/boringssl/crypto/x509/t_x509a.c | 111 + external/boringssl/crypto/x509/vpm_int.h | 70 + external/boringssl/crypto/x509/x509.c | 157 + external/boringssl/crypto/x509/x509_att.c | 375 ++ external/boringssl/crypto/x509/x509_cmp.c | 474 ++ external/boringssl/crypto/x509/x509_d2.c | 106 + external/boringssl/crypto/x509/x509_def.c | 98 + external/boringssl/crypto/x509/x509_ext.c | 206 + external/boringssl/crypto/x509/x509_lu.c | 688 +++ external/boringssl/crypto/x509/x509_obj.c | 197 + external/boringssl/crypto/x509/x509_r2x.c | 113 + external/boringssl/crypto/x509/x509_req.c | 322 ++ external/boringssl/crypto/x509/x509_set.c | 149 + external/boringssl/crypto/x509/x509_test.cc | 472 ++ external/boringssl/crypto/x509/x509_trs.c | 326 ++ external/boringssl/crypto/x509/x509_txt.c | 211 + external/boringssl/crypto/x509/x509_v3.c | 278 + external/boringssl/crypto/x509/x509_vfy.c | 2434 +++++++++ external/boringssl/crypto/x509/x509_vpm.c | 636 +++ external/boringssl/crypto/x509/x509cset.c | 169 + external/boringssl/crypto/x509/x509name.c | 386 ++ external/boringssl/crypto/x509/x509rset.c | 81 + external/boringssl/crypto/x509/x509spki.c | 137 + external/boringssl/crypto/x509/x509type.c | 126 + external/boringssl/crypto/x509/x_algor.c | 151 + external/boringssl/crypto/x509/x_all.c | 501 ++ external/boringssl/crypto/x509/x_attrib.c | 111 + external/boringssl/crypto/x509/x_crl.c | 539 ++ external/boringssl/crypto/x509/x_exten.c | 75 + external/boringssl/crypto/x509/x_info.c | 98 + external/boringssl/crypto/x509/x_name.c | 534 ++ external/boringssl/crypto/x509/x_pkey.c | 103 + external/boringssl/crypto/x509/x_pubkey.c | 366 ++ external/boringssl/crypto/x509/x_req.c | 109 + external/boringssl/crypto/x509/x_sig.c | 69 + external/boringssl/crypto/x509/x_spki.c | 80 + external/boringssl/crypto/x509/x_val.c | 69 + external/boringssl/crypto/x509/x_x509.c | 290 + external/boringssl/crypto/x509/x_x509a.c | 205 + .../boringssl/crypto/x509v3/CMakeLists.txt | 68 + external/boringssl/crypto/x509v3/ext_dat.h | 135 + external/boringssl/crypto/x509v3/pcy_cache.c | 284 + external/boringssl/crypto/x509v3/pcy_data.c | 130 + external/boringssl/crypto/x509v3/pcy_int.h | 217 + external/boringssl/crypto/x509v3/pcy_lib.c | 164 + external/boringssl/crypto/x509v3/pcy_map.c | 130 + external/boringssl/crypto/x509v3/pcy_node.c | 188 + external/boringssl/crypto/x509v3/pcy_tree.c | 828 +++ external/boringssl/crypto/x509v3/tab_test.c | 108 + external/boringssl/crypto/x509v3/v3_akey.c | 204 + external/boringssl/crypto/x509v3/v3_akeya.c | 72 + external/boringssl/crypto/x509v3/v3_alt.c | 614 +++ external/boringssl/crypto/x509v3/v3_bcons.c | 133 + external/boringssl/crypto/x509v3/v3_bitst.c | 141 + external/boringssl/crypto/x509v3/v3_conf.c | 460 ++ external/boringssl/crypto/x509v3/v3_cpols.c | 496 ++ external/boringssl/crypto/x509v3/v3_crld.c | 561 ++ external/boringssl/crypto/x509v3/v3_enum.c | 100 + external/boringssl/crypto/x509v3/v3_extku.c | 148 + external/boringssl/crypto/x509v3/v3_genn.c | 250 + external/boringssl/crypto/x509v3/v3_ia5.c | 119 + external/boringssl/crypto/x509v3/v3_info.c | 212 + external/boringssl/crypto/x509v3/v3_int.c | 91 + external/boringssl/crypto/x509v3/v3_lib.c | 362 ++ external/boringssl/crypto/x509v3/v3_ncons.c | 482 ++ external/boringssl/crypto/x509v3/v3_pci.c | 317 ++ external/boringssl/crypto/x509v3/v3_pcia.c | 57 + external/boringssl/crypto/x509v3/v3_pcons.c | 139 + external/boringssl/crypto/x509v3/v3_pku.c | 110 + external/boringssl/crypto/x509v3/v3_pmaps.c | 154 + external/boringssl/crypto/x509v3/v3_prn.c | 229 + external/boringssl/crypto/x509v3/v3_purp.c | 874 +++ external/boringssl/crypto/x509v3/v3_skey.c | 152 + external/boringssl/crypto/x509v3/v3_sxnet.c | 274 + external/boringssl/crypto/x509v3/v3_utl.c | 1327 +++++ .../boringssl/crypto/x509v3/v3name_test.c | 410 ++ external/boringssl/decrepit/CMakeLists.txt | 35 + .../boringssl/decrepit/bio/CMakeLists.txt | 9 + external/boringssl/decrepit/bio/base64_bio.c | 536 ++ .../decrepit/blowfish/CMakeLists.txt | 9 + .../boringssl/decrepit/blowfish/blowfish.c | 493 ++ .../boringssl/decrepit/cast/CMakeLists.txt | 10 + external/boringssl/decrepit/cast/cast.c | 408 ++ .../boringssl/decrepit/cast/cast_tables.c | 428 ++ external/boringssl/decrepit/cast/internal.h | 81 + .../boringssl/decrepit/des/CMakeLists.txt | 9 + external/boringssl/decrepit/des/cfb64ede.c | 236 + external/boringssl/decrepit/dh/CMakeLists.txt | 9 + external/boringssl/decrepit/dh/dh_decrepit.c | 103 + .../boringssl/decrepit/dsa/CMakeLists.txt | 9 + .../boringssl/decrepit/dsa/dsa_decrepit.c | 105 + .../boringssl/decrepit/evp/CMakeLists.txt | 10 + external/boringssl/decrepit/evp/dss1.c | 20 + external/boringssl/decrepit/evp/evp_do_all.c | 77 + external/boringssl/decrepit/macros.h | 123 + .../boringssl/decrepit/obj/CMakeLists.txt | 9 + .../boringssl/decrepit/obj/obj_decrepit.c | 71 + .../boringssl/decrepit/rc4/CMakeLists.txt | 9 + .../boringssl/decrepit/rc4/rc4_decrepit.c | 62 + .../boringssl/decrepit/ripemd/CMakeLists.txt | 23 + external/boringssl/decrepit/ripemd/internal.h | 493 ++ external/boringssl/decrepit/ripemd/ripemd.c | 324 ++ .../boringssl/decrepit/ripemd/ripemd_test.cc | 119 + .../boringssl/decrepit/rsa/CMakeLists.txt | 9 + .../boringssl/decrepit/rsa/rsa_decrepit.c | 103 + .../boringssl/decrepit/ssl/CMakeLists.txt | 9 + .../boringssl/decrepit/ssl/ssl_decrepit.c | 225 + .../boringssl/decrepit/x509/CMakeLists.txt | 9 + .../boringssl/decrepit/x509/x509_decrepit.c | 42 + .../boringssl/decrepit/xts/CMakeLists.txt | 9 + external/boringssl/decrepit/xts/xts.c | 258 + external/boringssl/fuzz/CMakeLists.txt | 66 + external/boringssl/fuzz/cert.cc | 32 + .../00c85e80891f1b88e11ee5a2502e0f682f0e60be | Bin 0 -> 1080 bytes .../02e0dfed35539f2a8fe487237de3cf6ba4ebb54f | Bin 0 -> 1022 bytes .../031c5183d8c8c560e8e1818ff82aabf33973f770 | 1 + .../039d65de40da4745433e149f9fb5ae66f8c90408 | Bin 0 -> 1039 bytes .../03b547e325434d1454dfdd34d4819f5b1e234fde | Bin 0 -> 957 bytes .../04ed1e2c50886acd723b3a78d4bafd49938bd14d | 1 + .../054cb963aaf9b554874b32275f44520641a11d41 | Bin 0 -> 778 bytes .../0694a2168fe7699e2dcabe3386a80bd4209094fc | Bin 0 -> 12 bytes .../08464c9f40426e219bdd673525af22a89b62c4d3 | Bin 0 -> 1934 bytes .../09406b74a5fd8ad9a82052a835c24dc3194d9704 | Bin 0 -> 1111 bytes .../094d3581e71a4316a567e43e6ebfa63b95196b8e | Bin 0 -> 1384 bytes .../095554da7da9b4234670b7f47cf9663c9c60c144 | Bin 0 -> 1316 bytes .../0969cd6815249cf0c66b302b20e71ef677b1c3e5 | Bin 0 -> 1217 bytes .../0b2f2af22568510301982a60fba3763b6ca92409 | Bin 0 -> 12 bytes .../0ba8e2a62b579b857e560bf1201fad463318c73e | Bin 0 -> 1959 bytes .../0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627 | Bin 0 -> 1021 bytes .../0be05d072f2f3828875fdfc55b04ff0f0ae9fc59 | Bin 0 -> 1041 bytes .../0c30def9baf58c5be015cede0594b4bd73507f00 | Bin 0 -> 64 bytes .../0d8ec36263c4e32e25e4ef1f01baed35b6227d3c | Bin 0 -> 1185 bytes .../0db3ab78e42c2aecbc7b898501c4f91ba91c200f | Bin 0 -> 64 bytes .../0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f | Bin 0 -> 1341 bytes .../0e29ba7cbd357efa6d2619ea98ef275e0b13a1de | Bin 0 -> 1186 bytes .../0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff | 1 + .../0fa9626b934e330a7cc18c118e31aad5639f2dad | Bin 0 -> 1027 bytes .../0ff9646573d3cbb8cfad86755ff52cad4788fcb1 | Bin 0 -> 1212 bytes .../1108c80f8912d5d9492de40e48dbdb7e44ae4a8c | Bin 0 -> 63 bytes .../1173445eb10e631879bf6b5cc168e2b8fb89dbdf | Bin 0 -> 898 bytes .../1288e7bc9178d23aa6662dc5348b8010e6b4ec92 | Bin 0 -> 997 bytes .../1293428367413052338e0b8b9e2660fea076f900 | Bin 0 -> 768 bytes .../1400c7baa454c64e5e1bc6454bfbef3700c881bc | Bin 0 -> 898 bytes .../148fc92ab76dab6ffbb59a544e9174ecf32f187b | Bin 0 -> 1131 bytes .../152bd97b8a6e893d704db2947e31f2e7dd7f9c63 | Bin 0 -> 1046 bytes .../159cc124352f0c0ac1cef2399c5c25614e29c6eb | Bin 0 -> 897 bytes .../15c89fc35e674fcd2fca3563669cc3c02db164ac | Bin 0 -> 1850 bytes .../162f227ef1629ac9a11a433bf124d297aedac5ef | Bin 0 -> 1058 bytes .../163fd7d62de6042f6353f383cdc0b700e0980f8a | Bin 0 -> 1317 bytes .../173db5dac0923eaaf0516593ec62ff48d07aa938 | Bin 0 -> 977 bytes .../183c776a51a73466cf9f32b5d22f05cf1348fa90 | Bin 0 -> 897 bytes .../1894a7ef9741425a741189996181a7b85773a94e | Bin 0 -> 1200 bytes .../1950704c247d49ee53fde32fcdff958b44bdd2ea | Bin 0 -> 898 bytes .../19a0a17b14c3a849d626f6b61219959343a575d7 | Bin 0 -> 202 bytes .../1a6654c8844f6eb41d34508e4330111cc14a4875 | Bin 0 -> 1053 bytes .../1a75d3e2d9ee4c34fb8d7506be6b2d762f6215d9 | Bin 0 -> 1109 bytes .../1b4aac6123267d5f6258899bb6ccd01747a87ba8 | Bin 0 -> 127 bytes .../1b9384af3bcfce2b1cb34dcc4541fc1177e18dae | Bin 0 -> 956 bytes .../1ba101e147f4453f2c709c037ae506cd79b6d7c7 | Bin 0 -> 897 bytes .../1ced169e5e3c017b015637eeb88afcd7d48bafc2 | 1 + .../1d61ed4eb67ed64942174bea48a77523a805a3e0 | Bin 0 -> 1106 bytes .../1d6b1f58a8be854b7667c019b5c470f3d325d575 | Bin 0 -> 897 bytes .../1d752734c8ecb0ffb7d98801159f9cfbd97e0d01 | Bin 0 -> 958 bytes .../2172996f7233ccd5607b6414058e64ac7c9bcdca | Bin 0 -> 1204 bytes .../2199b815cfe8b39732b8eb2847f6b5008a75d189 | Bin 0 -> 1494 bytes .../21a4835c0fe0b0a69bab262724f6356f7c008132 | Bin 0 -> 193 bytes .../22a7767a68debe1a1cfdb43355d2c9332ac88409 | Bin 0 -> 15 bytes .../2357c3ad0b6adfa54a5fe88b7f99b1c21416d304 | Bin 0 -> 1022 bytes .../23da98cdc1af6ef01ca8fad38ac021910832fe02 | Bin 0 -> 897 bytes .../245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed | Bin 0 -> 182 bytes .../24fad8b85d8f1129e12f742472a4895aadef1872 | Bin 0 -> 64 bytes .../25e586f9292916959c71561431fecfc188dcf69e | Bin 0 -> 1058 bytes .../272ed7d95717a523c65e5cbf1849f89041cb58a4 | Bin 0 -> 1850 bytes .../277042c5f5018c9e4ead5db206baf143f0a1a9a1 | Bin 0 -> 64 bytes .../29164dbd53e8108c324376573091e4c4213d5bf4 | Bin 0 -> 887 bytes .../2957f98f3f77110b8a05a8d67a1ff574f090c2b3 | Bin 0 -> 57 bytes .../29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 | Bin 0 -> 1663 bytes .../29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 | Bin 0 -> 1388 bytes .../2a0d8199c1117a1cee556ce8e13fdce6c00529f8 | Bin 0 -> 3 bytes .../2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 | Bin 0 -> 141 bytes .../2adda7db83a6e20697612ee835c58415072899f0 | 1 + .../2c3735c25b884954b3daf5fe573d89f5d516df4a | Bin 0 -> 63 bytes .../2c3743ad90044cc189240b7874e6e4df3ce69571 | Bin 0 -> 707 bytes .../2cd91be7451b6016cee440fb86e06c7afd157e79 | Bin 0 -> 12 bytes .../2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 | Bin 0 -> 1088 bytes .../2e1f157c8c157903e5e862dcb34fb3b7be376879 | Bin 0 -> 1177 bytes .../2e375a900fedc57b49326e77554e6550fdc1e436 | Bin 0 -> 1081 bytes .../2e4777559846e771a689f12bdc77806853cf4d08 | 1 + .../2ef6c305d2b8478403c470bfc09807d3cfedcd42 | Bin 0 -> 1469 bytes .../301c5e78f8b0334ee078e8e89eba2d9ea545d572 | Bin 0 -> 1005 bytes .../301f44ea637ab6dbc97d15ace5a3250215c999ad | Bin 0 -> 897 bytes .../312cbcea0df790d023073e9dc5de165190f86b5b | Bin 0 -> 1373 bytes .../31dad1d547e55649e2ca06f479081d5418d212b1 | Bin 0 -> 897 bytes .../3256b480f1212007bcb0e53ef124ead78ec30b9b | Bin 0 -> 897 bytes .../340cd6562eb74d264b8a8123b49fc3babb6033bd | Bin 0 -> 975 bytes .../3607fbd5d18f5f196e2ad467b39c31d80c136f06 | Bin 0 -> 1039 bytes .../360e330b02ff481851b528cdb2fdc952d21afa91 | Bin 0 -> 897 bytes .../3663d7a7c4840fccf48c134a13eed5156b44055e | Bin 0 -> 969 bytes .../3666ba893cec5a069376d0b91532ab4317b720a9 | Bin 0 -> 1569 bytes .../370522e931da2c14602da88ac1a9b781f0d7a17f | Bin 0 -> 770 bytes .../375a68f804031aaaf103a54625036bf419656cb0 | Bin 0 -> 1851 bytes .../37ea6223d496dd2bb8d317b752010198d1fc14c7 | Bin 0 -> 61 bytes .../37ffecbaa9a8f5540d94963beb62d93e8f1c568d | Bin 0 -> 1046 bytes .../3834b376516fd4984fc5dc3b8f42a1fabd74664c | Bin 0 -> 897 bytes .../38d7a3a0edc77172b1663880ceda8d1ab373a0d6 | Bin 0 -> 897 bytes .../3922605043f42c4868f47dd2463d2858fadfe0c4 | Bin 0 -> 1111 bytes .../39fe902954bf3c1e0a033d33528e090c8c7835ee | Bin 0 -> 1039 bytes .../3b7f75154dca9e79b5662226dc6c939b8aa7ac33 | Bin 0 -> 992 bytes .../3bac41829e17f9dc2f349d90283030f97e9c6541 | Bin 0 -> 1631 bytes .../3c2763aa2e94dc845be54417f2ca9c1386720151 | Bin 0 -> 686 bytes .../3d1dc5780b01d8d4e3381d534b36ac875d2e8537 | Bin 0 -> 993 bytes .../3decf06ce7e54513145619feedb9ad5ba96e898d | Bin 0 -> 897 bytes .../3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137 | Bin 0 -> 1337 bytes .../3eace4afa12afe234d6ded7d08130217fc2c9645 | Bin 0 -> 941 bytes .../3f1f7551d55ebb535cb54aa24037a83275b0c89a | Bin 0 -> 1044 bytes .../3fa31bd76bae27f66b61c63a4abfc461bd371934 | Bin 0 -> 1839 bytes .../40ac31d214a40326d74fdf7814ca312288360fab | Bin 0 -> 12 bytes .../4225f4d93f8b87431acc7167a7e6ca27fe7d119c | Bin 0 -> 1394 bytes .../4257efd87e9368cde94e8e321ebff4f3a623dd5c | Bin 0 -> 1280 bytes .../4298a95b560d773b41276414f4f7e991126fe619 | Bin 0 -> 897 bytes .../4306c7e25b8389c7d3f402887a4077655ace41c6 | Bin 0 -> 1017 bytes .../4439d387e849de35ea6711c3819463345004b2e3 | Bin 0 -> 1328 bytes .../44d2f5537df291966ab6205ee71a809a8a56e866 | Bin 0 -> 2046 bytes .../457c25ce787e34b315d3b161a8b478a5e793c3c4 | Bin 0 -> 63 bytes .../45bec5a0ca33be77b2363ab59fb821aa44c55cbb | Bin 0 -> 1151 bytes .../4685dd4dae8033acdb72a6fb3a0ce71f1299a92c | Bin 0 -> 1081 bytes .../46904f9ce32352458c5e294c368797ae0e48991b | Bin 0 -> 1005 bytes .../471e13c4ef32ffa3867034fe360e142cd7699faf | Bin 0 -> 1317 bytes .../47c5db7df8938b05eb5344148af2ba4e6a6ebec2 | Bin 0 -> 320 bytes .../47f69c07723fe0f12f8f81d3a622f0ca09d693ad | Bin 0 -> 899 bytes .../4843ed9fc33451381b6f97311b8c6e254937f2bc | Bin 0 -> 1111 bytes .../484c387f1936612f6e742f10775fa81593cb0c47 | Bin 0 -> 1508 bytes .../4938a5264e0e29b97f1a10e1a51a0e7de8334a90 | Bin 0 -> 1327 bytes .../4a59656c14d04ce913197e47cde59133db0401c8 | 1 + .../4a7220ebd75b74c4b91bbde748ea273342e7d306 | Bin 0 -> 24 bytes .../4b32eb728bdaa1e1ce8f75344c9113f01addd7dd | Bin 0 -> 705 bytes .../4b5b5c5fafa6bd96ffc447488f2b283ef76287a5 | Bin 0 -> 279 bytes .../4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 | Bin 0 -> 1642 bytes .../4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5 | 1 + .../4bea495c65f278e4ec1b343819a713f062aaac99 | Bin 0 -> 63 bytes .../4c1470de173adf77388fd8be8206e5f987d468e6 | Bin 0 -> 1607 bytes .../4c1bb06706cb5a80f1c7ea2a738b129360823a84 | Bin 0 -> 1317 bytes .../4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 | Bin 0 -> 1625 bytes .../4cef0705d69922b19e4f50c16446115d03691379 | Bin 0 -> 59 bytes .../4cf5cbf6eff378231f206e345fe96ce8b8ce5057 | Bin 0 -> 1780 bytes .../4d19ff9e4518157c69e1a03d87d00f2eaa932a90 | Bin 0 -> 1624 bytes .../4e433c8a70e56cfa46a1ae7be617a9609540e59c | Bin 0 -> 976 bytes .../4f131a48839d15feb0fb9fc92e3cafb76975632a | 1 + .../51f89a8688c1b0fcdd806578ca485c7e4037f3c0 | Bin 0 -> 1059 bytes .../5222e890a092812b05c20232eca33516d61e6854 | Bin 0 -> 1196 bytes .../5357bd89f226463ea66378f1872f2f3dcc45c833 | Bin 0 -> 897 bytes .../536b9cd5f18e73b30687908443036be7a1b108b0 | Bin 0 -> 770 bytes .../545e53e61cfc711f2faf4556040d09fc8d8aaf2f | Bin 0 -> 1040 bytes .../54e8f165765c879ddb14f19d76b6e040a8269e23 | Bin 0 -> 1018 bytes .../54faf9d362f22ac220377a9d478731301876830d | Bin 0 -> 1222 bytes .../55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 | Bin 0 -> 1631 bytes .../55ff515a21332c377e8682bb0f05d4a36595cb18 | Bin 0 -> 2117 bytes .../5616542c0240af6572786b4088b07a3d6da77caf | Bin 0 -> 1217 bytes .../56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b | 1 + .../56ef359b39b367bc94f66501729907dfd8fb8425 | Bin 0 -> 64 bytes .../5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 | Bin 0 -> 1934 bytes .../5a7baa69f7c27ed50c560f427370910220cf4073 | Bin 0 -> 61 bytes .../5aa3c8afa0c89038c509026d2a48d790521f92a5 | Bin 0 -> 897 bytes .../5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 | Bin 0 -> 1055 bytes .../5c7389e097519d3d2c974b7d082344c6fdb9e74b | Bin 0 -> 992 bytes .../5ccb2368d4f51967b4d79b062103604a0e73c6ab | Bin 0 -> 64 bytes .../5d00700f69a1db5a65201dc8d56aa917c6e6132b | Bin 0 -> 1200 bytes .../5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 | Bin 0 -> 1492 bytes .../5d5680962803669e9a931bc79eb421002bb6abdf | Bin 0 -> 897 bytes .../5d64f19209be8be3ce3e914b475db34591d7a985 | 1 + .../5d6ffff8423a44c92868994adb23e851b6932224 | Bin 0 -> 1502 bytes .../5f6a0d4e63e434e50dbf1159514610e031afbbc9 | Bin 0 -> 998 bytes .../5f7cc578c2516d3b9465841482354b609fee62fb | 1 + .../5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31 | Bin 0 -> 1205 bytes .../5fe171e9917a45ecee64fd75cdc3726a0dc65a5b | Bin 0 -> 836 bytes .../6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 | Bin 0 -> 898 bytes .../60c070cf2975070c6def7c702abd7d7d941ae0e9 | Bin 0 -> 818 bytes .../6118a3fcc0337a2cae92be95b87dcdc47a2c53c9 | Bin 0 -> 64 bytes .../6461be4247a144f92150a896c56f9561f2169337 | Bin 0 -> 160 bytes .../64a9ce67fccd9c0a3b2ff3d02ea9afbe5619b41f | 1 + .../64f00e208a2077bce3a031aa41a2dd696d012715 | Bin 0 -> 12 bytes .../65459fb5f394db61715e19187239b7aa90b1719b | Bin 0 -> 897 bytes .../65769e24f85a4467ff67707ede0c56b5e7046687 | Bin 0 -> 123 bytes .../65b1bfb6b449b875079f932a6075771dba978141 | 1 + .../667d0776ef5074ba6525d5a56fbf3ff140108a33 | Bin 0 -> 64 bytes .../66cb9a69e7289f878d3f9bdb235bb4ad97e138b0 | 1 + .../67c6b2d857ae3edc271adac024751559bed7ae97 | Bin 0 -> 941 bytes .../67f672ab618d2facc0092cd32837cc04e5d37216 | Bin 0 -> 1111 bytes .../6869834d4b7c77e0bd7ce160876197a3c9be7040 | Bin 0 -> 63 bytes .../693913decd386589e4d4212fc498714506d667f0 | Bin 0 -> 64 bytes .../6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148 | Bin 0 -> 193 bytes .../6e58bd8357c877fe7e3ca75af4b9959831ee44b1 | Bin 0 -> 976 bytes .../6f0d97a3ed2a4c3c330edb10959f005a553d08f4 | Bin 0 -> 382 bytes .../6fe20105baf3a79f9c69ff4dde501c4542118d06 | Bin 0 -> 897 bytes .../70be2630942a6f72e66f3f7189ad014acc45bb7d | Bin 0 -> 1958 bytes .../70f2004db5c4ddfa9bd91d0db596867b4403d9cd | Bin 0 -> 1044 bytes .../71123779ed3db9713684829f9a2ed309c9d96f06 | 1 + .../719702d86cd0fc94ad0b193398112815f3308744 | Bin 0 -> 1336 bytes .../71b0adb1b0c1fccff4150b015220e74e549d24d3 | Bin 0 -> 897 bytes .../72273c2fa36dbb9b39a69e65f59b616c706f3330 | Bin 0 -> 1302 bytes .../72b8b2c9ae429de1590b68fd125892a3832abc5d | Bin 0 -> 621 bytes .../72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 | Bin 0 -> 1492 bytes .../72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 | Bin 0 -> 1777 bytes .../7345d2f36ce35f7aaeb3f3c62a2b37f55dfd7af7 | Bin 0 -> 59 bytes .../73c845434d7055e1cff670fe85edb1b7581ee224 | Bin 0 -> 1081 bytes .../73fa79cca934a2c5c13f7d41b0162e611d6e4f5c | Bin 0 -> 1432 bytes .../74287c085825b190ed3cf50ad0f5beec7cc07edd | Bin 0 -> 63 bytes .../74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd | Bin 0 -> 1137 bytes .../7685b3e299f2cce95aab0d8559fd45d8198f5da2 | Bin 0 -> 10 bytes .../771688184c18822e2182b18bb1ec853a88262659 | Bin 0 -> 15 bytes .../772739edb5a338fade2b33ed8c4c7e5c3856e7bd | Bin 0 -> 818 bytes .../77818abcde8b135fcc987e61388553e697d32d75 | 1 + .../785389bce6d1f4c8f2cec6062ecacb1d49a784f9 | Bin 0 -> 10 bytes .../78fa5096155d1b72a074a486cf7ace40a4c92f1f | Bin 0 -> 5 bytes .../795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 | Bin 0 -> 974 bytes .../79fe694f60433debeb203f01dbacefcde6e9483f | 1 + .../7a37f6614fd5c0dda82eceb3d171090c7581f0c1 | Bin 0 -> 897 bytes .../7adda79c5f85db9577eac0cf60e0cad63c74e144 | Bin 0 -> 1098 bytes .../7d8eed80cfd58de130245bea2880f3b042225847 | Bin 0 -> 1221 bytes .../7e87ff06a8c83b1195fb15a9d599abfe28b94cbf | Bin 0 -> 995 bytes .../7eb1f7349c812a0ed94fe21f9900600516164b17 | Bin 0 -> 993 bytes .../7ecb46c93915184be12fa3cbaac3b65072116242 | Bin 0 -> 64 bytes .../806fd814b69bc6511d7f6e1a3bc762d14a56364a | Bin 0 -> 1217 bytes .../808871bc380bc3221c7ce683031bb6d85293ee5f | Bin 0 -> 1020 bytes .../808882216e9afcc5257f494435c2d9757dc785eb | Bin 0 -> 193 bytes .../808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6 | Bin 0 -> 897 bytes .../8210a65e177303f8b801f73c663806236584988b | Bin 0 -> 23 bytes .../8217aa968f0050b2fb1aac92ae6f377c41c3952b | Bin 0 -> 57 bytes .../8369ebff6d1524579c2bcd10b5ab2df186cba6c1 | Bin 0 -> 1642 bytes .../83a5535a9a577453d218f897017e59a996439c48 | Bin 0 -> 1730 bytes .../848426625248d49961481ba4616c501a808983ac | Bin 0 -> 1055 bytes .../84882a41d7892f52a3145178b9ff8ad6947ddbf4 | Bin 0 -> 11 bytes .../848f69b34380f7554ab3074737d72ca8b0264def | Bin 0 -> 1256 bytes .../85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85 | Bin 0 -> 1131 bytes .../86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 | Bin 0 -> 897 bytes .../8786dd7aa2d0ea06461fc1d4751c9c00e234e57f | Bin 0 -> 244 bytes .../8816b6afa44700585efccf15d9b4b0ebdaa57668 | Bin 0 -> 767 bytes .../883b4622778cad8346c050139607cac3ff967b35 | Bin 0 -> 1849 bytes .../8853ff143e14ef222a6c7044ea50992b53ed7387 | Bin 0 -> 61 bytes .../888fe58059dfa918cfa17edfeb3746c709050ead | Bin 0 -> 897 bytes .../88bc068b97b79216220812a038ebb2810b26886d | Bin 0 -> 671 bytes .../88e90e49acd2ab796a48eda68f66529dd4206671 | Bin 0 -> 64 bytes .../88fd1e4a65f306244552395b6ca6534a20982b8f | Bin 0 -> 1839 bytes .../8a27963ce5bb499fea5f1fc3a2876e4f5a21fade | Bin 0 -> 897 bytes .../8a677dfa5510949833db9b79ae63bd4a5d882665 | Bin 0 -> 1469 bytes .../8abde7f7cab98c1b02729fcd665090c8b0934431 | Bin 0 -> 71 bytes .../8b188b379875299b1f6ca0501cf758b3a313a7d8 | Bin 0 -> 61 bytes .../8ce5aebbe8c9d1562a2ae1b996669f1843692c4d | Bin 0 -> 1041 bytes .../8d181c10f73a5574cbf445593200e71a16584ec3 | Bin 0 -> 1631 bytes .../8dbbc76831fa9eaff21b8a04f5ce41c1a0468538 | Bin 0 -> 1019 bytes .../8f5cdec4e18527ddbc930a7bfe710ac015527f00 | Bin 0 -> 70 bytes .../9070df87024c0167e6a1bd9512f698d3a31ca0b1 | Bin 0 -> 2626 bytes .../90fbdf2d500b38c15e3364d041484cf065cba9df | Bin 0 -> 1060 bytes .../92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a | Bin 0 -> 998 bytes .../94b7796d627b110ff66c1bd9dc1a7c2f87a723ad | Bin 0 -> 771 bytes .../94d777c0eae1377aa35069f15e75954792406394 | Bin 0 -> 1096 bytes .../953b46659c6224c0068a9ddb3fa7b0a74f89af3e | Bin 0 -> 64 bytes .../96516b3b33c6faa0224d198d549b6a167416a4f6 | Bin 0 -> 897 bytes .../96aa3fabebccf825b9cc06ec34e605a450b49eae | Bin 0 -> 128 bytes .../96ce1cb3ca0061f2865d1348f3e147000a3b1a93 | 1 + .../9716858fbfa71a1c8bc855f2a09dece8df15e5bd | Bin 0 -> 262 bytes .../97335aacabe616a3b92c25187ef3ccc58dc09fad | Bin 0 -> 897 bytes .../9827e8a5ab0f09782c75a948175d723ea6fc54db | Bin 0 -> 144 bytes .../990a8dcc9aadd0b161023f0d16e6556e30ddc631 | 1 + .../9948b60fcf547feec8bdd433a1dde37e2cd34de9 | Bin 0 -> 1041 bytes .../999f2f88a8b6510ca0253005f3a6cc06840a8079 | Bin 0 -> 1096 bytes .../9afae58a2080ea211e3e5b25f4c35c0aa3c341a3 | Bin 0 -> 975 bytes .../9baa5f344ecd37e2762cb8a7497709b78d69cae6 | Bin 0 -> 64 bytes .../9c719bffb73cc4fa6a3bba4acd487049eb781a7d | Bin 0 -> 1112 bytes .../9d20961e30091256f8211c2837a35db60411dffd | Bin 0 -> 1004 bytes .../9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 | 1 + .../a0666bf912f161ed73664e328cdd57d59118e3a3 | Bin 0 -> 195 bytes .../a15fa9644e1be0193331158823bf88ff51593bff | Bin 0 -> 1082 bytes .../a19ed2ca60eddf4a56e318b33c4767194efdd420 | Bin 0 -> 1088 bytes .../a29b87920a4c706f69a58c61e7d22aaa26a781a9 | Bin 0 -> 1372 bytes .../a330339d9f71af3b1ef51f62aacf3e5a18233029 | Bin 0 -> 1869 bytes .../a3332f9638dc9ec85e9c2166128bf7eb8ebb005f | 1 + .../a36107992ae6b6dca220e831495ba60a4e817681 | Bin 0 -> 884 bytes .../a37c3ee4668153e5ef9c272d43a2545a75b36854 | Bin 0 -> 939 bytes .../a46eda9b97888af5263bc32293f940a8c2125ac3 | 1 + .../a5061c9bd9b94e35318ca968a7f933147ca56e83 | 1 + .../a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 | 1 + .../a63ee3d25f38c1cca2b1498b548396d900e8741a | Bin 0 -> 897 bytes .../a6447b7b3c50340aa14feb960245856ddeebc2cf | Bin 0 -> 1219 bytes .../a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d | Bin 0 -> 897 bytes .../a758736dfeb57d7bb7f31793d81bab116942d31a | Bin 0 -> 1254 bytes .../a83ca2374044aa6547ce0cd931cea82f34bcfbeb | Bin 0 -> 996 bytes .../a897327b805c8b342ef8ad32adc92e904ee16bcd | Bin 0 -> 1040 bytes .../a8be778f7892a8d914e7d742529143c57959e457 | Bin 0 -> 1040 bytes .../aa94b8c126db37057eba60ebf9ee8424c4dcd931 | Bin 0 -> 62 bytes .../aa94e8277aa662cf0a17f930b9724e0c39699db7 | Bin 0 -> 897 bytes .../ac7ce7801f5c13864f06b098b137bcca98c9dd4a | Bin 0 -> 897 bytes .../ad0875493831e5d809ec58af56dc27736d8da4cf | Bin 0 -> 61 bytes .../ad520c064da535365c2cf4262dc960cc03011a0a | Bin 0 -> 897 bytes .../ad6d7bb7923133cf1bd53c824cd8f400359430e2 | Bin 0 -> 897 bytes .../ad987767605d380e8465acbca66ea6b74158e4f9 | Bin 0 -> 216 bytes .../ae096884e1100954f53c3e6c79845e94d4d9a746 | Bin 0 -> 603 bytes .../ae6c9f7732c5b28312dbfdd0d2708050e056f85b | Bin 0 -> 2009 bytes .../af72aeeb36675d40d33838d25bad17ebe69e95eb | Bin 0 -> 70 bytes .../afebf1b47d59c6c659856c5858596d646d42048a | Bin 0 -> 1020 bytes .../b0bbe893c3557ffe322c9acbb268f58bd6f6ab9d | Bin 0 -> 55 bytes .../b240ee6879847aa20ae97315c6062da51a223542 | 1 + .../b255b3d96ff0a405b5c782cd18fbc50034d09793 | 1 + .../b2617f1a96f347b9d3d08f52e2459de63daaae63 | Bin 0 -> 897 bytes .../b27f0261d700798b8499047d9d3e5a4330ff1b99 | 1 + .../b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 | Bin 0 -> 897 bytes .../b33bee76673e45a532c82df4459d8f0efca9b024 | Bin 0 -> 897 bytes .../b496b414ddd42dd3d1633921131dab70ee93f9e8 | Bin 0 -> 897 bytes .../b5442281d01a098f07aa150dc8c8ebc432922b74 | Bin 0 -> 1342 bytes .../b569b141740c0b32d4f8f8d77fe603287cf4d902 | Bin 0 -> 969 bytes .../b5f5a28954d2634baf685a1790ce013ca0f0f951 | Bin 0 -> 72 bytes .../b612998fc4201e2955aec046387e95254b25ba29 | 1 + .../b63a8d0e7c1848019b4e4e8e19d14adec00b7c19 | Bin 0 -> 1023 bytes .../b6934c620f93440e12cf5861f588ab3574da9a84 | Bin 0 -> 1919 bytes .../b6b89469619a6e0194005e993cf053cae6ff9fda | Bin 0 -> 959 bytes .../b732cd2e2227deff1529a431a16b3166bd66f0ac | Bin 0 -> 1106 bytes .../b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 | Bin 0 -> 1002 bytes .../b88401cca46b7cc9cf588dbec641411101bbce68 | Bin 0 -> 2056 bytes .../b8c68e6426d5993b9c08d0384dce5d52014254a6 | 1 + .../b8f244f0d4a928ec6e532af4c7c633c99de03ee2 | Bin 0 -> 1193 bytes .../ba485873c6de244c1d036607fd57107bf3d54399 | Bin 0 -> 745 bytes .../ba8ffb341293741fb442ad7817290bf57acc87f0 | Bin 0 -> 1081 bytes .../bae9b0825a33ac52cd413665dd38a17837174a7e | Bin 0 -> 71 bytes .../bb1fb206c56745bf992220e6c7de0e2fc94cf068 | Bin 0 -> 896 bytes .../bc01d9510d91bcf2ba747842a572140801564b92 | Bin 0 -> 1110 bytes .../bd32136e6ec853a56e70060a2c308187b8fccf65 | Bin 0 -> 1188 bytes .../bd351dbed468c58280ee4735c6fe101813bb767c | Bin 0 -> 898 bytes .../bd49114ebfcb9795f8231b482ad700f1dd092def | Bin 0 -> 976 bytes .../bd72b9ca5d91970e5b77e97a67781e3e70810edf | Bin 0 -> 12 bytes .../be96bcebf50e143552339a23071c9994bb7b5548 | Bin 0 -> 1106 bytes .../bf89b0f5278535c052386adea67874b12668fca2 | Bin 0 -> 898 bytes .../bfa6177702f7b3d35d431d805af1216b3ace3a28 | Bin 0 -> 1280 bytes .../c10def6097a072cd11a89161c49c76f4cd9b851b | Bin 0 -> 1041 bytes .../c218be470382eb7b9cf45659c58d66bb000f4eea | 1 + .../c2b238783ccd5d9a8ab37f45e12001e2d32634b6 | Bin 0 -> 1102 bytes .../c3c6d8be363e9b8535dc6586a6b01122efefdea9 | Bin 0 -> 823 bytes .../c4437538c745e35381b74aba56778cfa6379180b | Bin 0 -> 897 bytes .../c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 | Bin 0 -> 976 bytes .../c45c2dd1094d4b93f18f081c0b576bae60bb27d3 | Bin 0 -> 1853 bytes .../c47cc42321d347f0b8596e94c53ddfc0c5a90a88 | Bin 0 -> 33 bytes .../c4f3c6cfbef081bf63b3b5972c9137635d445fdd | Bin 0 -> 897 bytes .../c4f605ca070c95dc5d1fd59124a12d35e8c76008 | Bin 0 -> 897 bytes .../c549b74782b8ee587cea2d773c76f736774a1040 | Bin 0 -> 897 bytes .../c613a74f7c25acd72e426aae6b6f8aca4230de92 | 1 + .../c6b5b66f8a56110cef76c49e0f128584ff9ae744 | Bin 0 -> 897 bytes .../c6bb980166717e341bc7628fdcf7e6857f42b78e | Bin 0 -> 63 bytes .../c885c076019c097c788823b5c242789315ce18fb | Bin 0 -> 1373 bytes .../c8fe6b745e1bed025f2948444e1372cf89bf2f54 | Bin 0 -> 2048 bytes .../ca5f6f2655ef6d5737e61519eddd94cecbd9aec8 | Bin 0 -> 5 bytes .../cc70087dae81f66673015fe1f97b13b0f1d7256d | Bin 0 -> 1446 bytes .../cca7bdb3e8b8c03d754aedbb5f781644305d3644 | Bin 0 -> 996 bytes .../ccea62417883c07b37d5f8120602b78e96cf18ca | Bin 0 -> 1041 bytes .../ccf05090692d99c4c28dc2e104896819ed3fdd9a | Bin 0 -> 1528 bytes .../ce1b40306ee7b3df129aa772c11103f7237aa1ca | Bin 0 -> 1378 bytes .../ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f | Bin 0 -> 991 bytes .../d16735101a64c74e14692a65c2ca06abb8d9cb0d | Bin 0 -> 562 bytes .../d16b443aec52814ed1678cb3b02ee561b6f1889c | Bin 0 -> 218 bytes .../d3c601c2ca8db7dbeddb254cda2d91cadc036e61 | Bin 0 -> 897 bytes .../d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 | 1 + .../d51782b160d3dacee93a1dc34cfec9a7ca4a6c53 | Bin 0 -> 61 bytes .../d5c2fed75bc049b570bd445b9461a1595f880dca | 1 + .../d5c3e609d1685e2a11e63622d71cba7cc8a73590 | 1 + .../d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15 | Bin 0 -> 252 bytes .../d665df68474dfd7f768ac8f202455cebf498724d | Bin 0 -> 897 bytes .../d6df7b56969b3f2bd6c323aca98179f1f3ef3396 | Bin 0 -> 879 bytes .../d74eeb9a616344007edfa077561a95bd1874152d | Bin 0 -> 1431 bytes .../d7ba4e58caa05b0c3bd0f5258adf1429d022632f | Bin 0 -> 968 bytes .../d805c1da8681e325ad44cf57dbac466ca77efca8 | Bin 0 -> 1102 bytes .../d88ae7db4ae813bab4769563be5290808a004796 | Bin 0 -> 2048 bytes .../d93f2f96d294071ed098a03d86ed46d71919e7a1 | Bin 0 -> 990 bytes .../dc999ae9538c03dc88825fb62c92d98a8d8e48ee | Bin 0 -> 897 bytes .../de05b31a05846f00be753f15be9242b01396a553 | Bin 0 -> 88 bytes .../de0df75a8e629a16586e75477510bb7f0093f674 | Bin 0 -> 986 bytes .../dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e | Bin 0 -> 1838 bytes .../e1749e1d3e67cc947379ece199ded471a5e55c79 | 1 + .../e180125371c88bbab75d9aac4d6b1144e0f0683e | Bin 0 -> 31 bytes .../e350aef7327491a094f8a8bc3ca01ce636e9b945 | Bin 0 -> 1766 bytes .../e4c5cfd43a153699610e5456b0b58984bdc36b25 | 1 + .../e662bc8b0f1bcea6081c65fc1195e6df53a51961 | Bin 0 -> 1261 bytes .../e67cc75ea22aec3e31ac08718a0e8ebb49d0378b | Bin 0 -> 13 bytes .../e6d0bda14de5fabf61d6a77ed9de9dc32751c193 | Bin 0 -> 25 bytes .../e8d362075baf5e7ffa283a1f685ecfe270b756e3 | Bin 0 -> 897 bytes .../e9617db6d8b651b46ea1ef7b904887d3259d8721 | Bin 0 -> 62 bytes .../ea796fb39b55459c01da8f1aa538c91b9a3e0419 | Bin 0 -> 897 bytes .../eb0f13db27c5f72eef417ac98c8d5b326f40d229 | Bin 0 -> 1905 bytes .../ebb2f919adba543e9f61ba5ffd13e89c9422f70a | Bin 0 -> 10 bytes .../ebf19e8523e49eabc87277ada0e355d096d5cddf | Bin 0 -> 112 bytes .../ec19b8e77fa86a2aa5602a6a45a8a6df7b334794 | Bin 0 -> 766 bytes .../ec32acf8f685b186fcfe11250167c70174cbea22 | Bin 0 -> 1088 bytes .../ec32f05544e071fea1ec748e9a5692e85a490cc2 | Bin 0 -> 1624 bytes .../ec755a11cd589bdd907bbb67b83f41e3b49f42cd | Bin 0 -> 1192 bytes .../ecac00e857f10a143e5760a8d027498fdb46cbf4 | Bin 0 -> 64 bytes .../ed5c5806eb26764f7aa87b897ab67a1df82dbf53 | Bin 0 -> 1177 bytes .../edf23858b6ac5eb22f6e573f9d6edae229b9c100 | Bin 0 -> 1244 bytes .../ee895bc6274dd27e4a6f18e26d598846f4b15e95 | Bin 0 -> 1244 bytes .../efb28c035f9c8a62a312dfe83434cddbc51b4c8a | Bin 0 -> 1382 bytes .../efbda51a6d24e19451c4445f985b85fe04b87a93 | Bin 0 -> 897 bytes .../f00aedcbd7394eb866d433f49f04f6d252d3fe44 | Bin 0 -> 1088 bytes .../f00bfbc36ddb3d9cf089414ff7dcfc973927987c | Bin 0 -> 161 bytes .../f02539e797ce16b7842fe95cfba87c44fbf92119 | Bin 0 -> 897 bytes .../f0cf1c8a091014b0ddd88edb3e9567370cb5d741 | Bin 0 -> 888 bytes .../f167e20b679ab2689a5723e39c19c33fc3b4c9e8 | Bin 0 -> 1224 bytes .../f34b279011e9a03e95b85f6a8d5e2a59089fe516 | Bin 0 -> 1160 bytes .../f44630078d74ae4e135a62d7477847b24b399bf1 | Bin 0 -> 1396 bytes .../f588df591762aeb4f9cef3e2d63ab34cbab3567b | Bin 0 -> 1927 bytes .../f8e817dc5c2b1f27d31240841ade404d15606742 | Bin 0 -> 61 bytes .../fbd5fda7debfed22a821cd1c796f2ecf459a14a0 | Bin 0 -> 887 bytes .../fca0bbdfab4ad790670f079ac242c12a5c7fa58a | Bin 0 -> 886 bytes .../fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac | Bin 0 -> 897 bytes .../feba41538668e8c9eb82132ca606c0fd7f812547 | Bin 0 -> 151 bytes .../feefb266829c616c907a1d4accab0287ef47c2c2 | Bin 0 -> 897 bytes .../ff46d1b4923b92b30fa6fd9a7e429ad1cb1f9e7f | Bin 0 -> 1208 bytes external/boringssl/fuzz/client.cc | 55 + .../00717d11ddde89f0895bf72de8de3bf99d1b5c46 | Bin 0 -> 3954 bytes .../008ffccde65bd0671279ec86741c59a52e0dd87c | Bin 0 -> 674 bytes .../00a71e9e98b44548faef02dc058b357edeaf6e88 | Bin 0 -> 3983 bytes .../00a98becb30742ad93ddeb7c851dd34f369d8e86 | Bin 0 -> 737 bytes .../01e050c8b311caa72bebb132b9fe98e22ac56682 | Bin 0 -> 3955 bytes .../02551a10425ba3ad2afdbefb411ff64aba801dee | Bin 0 -> 2420 bytes .../02c7b35834a45ac78a329ee5ed00bb55b2885678 | Bin 0 -> 908 bytes .../030f1cffd7e368013256e33ac467b978fbb60d16 | Bin 0 -> 3775 bytes .../031b3b89e72498be49f6cf81c83993686097fba2 | Bin 0 -> 3202 bytes .../031f30a25eb84fc9585ffa6d9f8ad2a6910a450b | Bin 0 -> 3181 bytes .../03b58ffa513cd4ada2eab899bf1399530dd1bf05 | Bin 0 -> 3309 bytes .../03e3208240d13bdbe7f9c85e49c2059c69b35c45 | Bin 0 -> 2606 bytes .../03e6058b6fad092499130b6651f3cdf2a937eec5 | Bin 0 -> 2721 bytes .../03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263 | Bin 0 -> 3572 bytes .../046d8a2ca8e3e68dc1b555e46ac4d4a6d2491982 | Bin 0 -> 2435 bytes .../0513ed635daf437c5a28ca633f74646a61ca6865 | Bin 0 -> 2905 bytes .../051cb5c1e3b99a50ff1a9b76944011402b738083 | Bin 0 -> 3615 bytes .../052085640421d4472a5597cc6b4f86104a8c9078 | Bin 0 -> 1015 bytes .../0526966b0ebf7fe77e4dee7c39fe7f0741730520 | Bin 0 -> 1229 bytes .../05580dbaccccb94d23cbfc8bab5a1d299ebe79ee | Bin 0 -> 3755 bytes .../05a05196a8e0958f1ba744d122208d337a8696fa | Bin 0 -> 3627 bytes .../05eb6bb7db04c88f052471a36c9937431f2e51a8 | Bin 0 -> 887 bytes .../063c1c4256bb77dcd3abaac0dbe28071bd749343 | Bin 0 -> 3330 bytes .../06e7df8edebe9b55ffe0279cc19b46b88ae76aa6 | Bin 0 -> 2491 bytes .../06fa70728c05d229e2dfa67ff3f0172feae65ff3 | Bin 0 -> 3404 bytes .../07559907aedb2924c0084232c2a50ce815443f0d | Bin 0 -> 116 bytes .../075c12272d2e7c3b9dacac07ea89f69c76d8968f | Bin 0 -> 736 bytes .../07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85 | Bin 0 -> 951 bytes .../083018618734196e3979d96b571e627909d8be0a | Bin 0 -> 4096 bytes .../08310c6bd2fd887cf1f5933965c9321bc3a96b35 | Bin 0 -> 1615 bytes .../08719b765365d265aae6a3ca7e5cc45e92e4c740 | Bin 0 -> 1092 bytes .../089063763289688a92b523abe0b21dde1dcb5903 | Bin 0 -> 3977 bytes .../09225c1125fed526539a962ff46972676518fa34 | Bin 0 -> 3829 bytes .../09a8967150d2ecb7b2adb5cfacf86e754274a145 | Bin 0 -> 1511 bytes .../09ea428e385f7cedefdd33c6e46ded0c26eca099 | Bin 0 -> 3676 bytes .../0a3cb64ca50c3eddeb4f38d82bb300896ce258d5 | Bin 0 -> 909 bytes .../0a44610c64874e172780e8e51b10031b0a2a4103 | Bin 0 -> 3911 bytes .../0a7fc3b19f7aa0892008f89d2540cfd652d924a0 | Bin 0 -> 908 bytes .../0b1614426dcada7c22eae8bde20c9ea1955af192 | Bin 0 -> 4096 bytes .../0b251113d82bdc624c418ca3e9a822af3f43f4bc | Bin 0 -> 3650 bytes .../0b393412092142d934bd3021e9ab95fa9c433de2 | Bin 0 -> 4096 bytes .../0ca74dfc9546ed626a103ffece16d214b0b4629d | Bin 0 -> 1000 bytes .../0d860a629f778931860041c502a048b562c5b929 | Bin 0 -> 908 bytes .../0d9891ca130cb689545acefd20ccc979e4b53f27 | Bin 0 -> 3332 bytes .../0ee7921127cd9571a51441816b048a4f340ac51d | Bin 0 -> 161 bytes .../0f14ae60b90b40bee0fec50ab06886127a245c28 | Bin 0 -> 3590 bytes .../0f7df9d0bc3a0978204d37dc4c74034e32438d9f | Bin 0 -> 675 bytes .../0fd8481bfc9ea37bbd7fc33dce344bca965b04ad | Bin 0 -> 3920 bytes .../1018b39874ea33fd123605bffa8986270e6ba538 | Bin 0 -> 3465 bytes .../10b4b91e0940fcfaa7a4f0959f2079ed70ae7370 | Bin 0 -> 1767 bytes .../10d8e6931cf75e896c8a6ec1081df869e30310e1 | Bin 0 -> 3577 bytes .../111bb472fcf4fc134af5ec3c189f43ef9ef19b36 | Bin 0 -> 3342 bytes .../1175419b73c59b028cb36d263fe31dddff6ed54d | Bin 0 -> 1851 bytes .../117e20e32c26799a3228a2b1fa2cbe39c8440720 | Bin 0 -> 1616 bytes .../119735b91048ae492dfb7459aaa01d7fe13c767d | Bin 0 -> 3576 bytes .../11a132d5dd71f67c2386cd2f6a5a256572423c8f | Bin 0 -> 3289 bytes .../11d92649d0dd312e6328dd34231e4bc56ee7cfb8 | Bin 0 -> 3994 bytes .../11da8204a79299f2855dbeddff540442ac33ed4a | Bin 0 -> 1658 bytes .../125a95886e4a7240566a17221a4453078a659d1b | Bin 0 -> 3407 bytes .../12852dc6e23d0eb6dffa19470b4d44f0105d6a5e | Bin 0 -> 3572 bytes .../129f293ffb471c54f0a65ebe68e8c03ae20edc63 | Bin 0 -> 3586 bytes .../12a16512ec0e3937654b4d283d70c7506cbeffbb | Bin 0 -> 1616 bytes .../12b0df532889077124403153935a3d4902a6268d | Bin 0 -> 3535 bytes .../1364b4aa04c2515df069617f9de27a1311e5b526 | Bin 0 -> 3588 bytes .../13e9182cb5db0720afec91acafe85fe3bac18d49 | Bin 0 -> 3570 bytes .../1413c7537c6e54d1c9e36d5559eee4c6f4bebe36 | Bin 0 -> 4096 bytes .../143cce6709b4f9760b89dc6920b427e2628db95e | Bin 0 -> 674 bytes .../14c3e63325718a0374c028dcd127d952bd5e063b | Bin 0 -> 3175 bytes .../15a54d5f346c2fd9fa3da6f73cee5db2c7952f68 | Bin 0 -> 3436 bytes .../15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6 | Bin 0 -> 1602 bytes .../1617afc9570c0c60a70fc6c93313203df55e35f9 | Bin 0 -> 3099 bytes .../1635f341671bca1a04ff2a13c8c3c54f914288bf | Bin 0 -> 3189 bytes .../16673ecbbfa4b6a7e0246386e0ee2785515ecf0d | Bin 0 -> 990 bytes .../169f2b81de0de2a0d403d21ca7f9ed0da77eb644 | Bin 0 -> 1619 bytes .../16dc8080d01278cfb39ee1c6836fe9d3b7e55436 | Bin 0 -> 3887 bytes .../1701cb50412ff3dd90f63cc9380bdf9421a9b8c7 | Bin 0 -> 786 bytes .../1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a | Bin 0 -> 958 bytes .../1737b38dda86f8045b2ec419664c9cba31d02801 | Bin 0 -> 1228 bytes .../175b59e886da4e09ecac6c84b39a6f30b37c6dec | Bin 0 -> 1354 bytes .../1825f52717650a3fac3cd62f5250255a83b9f4ae | Bin 0 -> 809 bytes .../1856b18ba40b75802c03e5216393950a32cdbc6d | Bin 0 -> 3615 bytes .../185e35d9e0d325e70f58efa24fbee9f4edce6c1d | Bin 0 -> 909 bytes .../189eec7d1e6d85b7cbc91c0320ea8643426e3ccd | Bin 0 -> 736 bytes .../193183a77f39a2ee7a54d2cd86191fcbde1c5924 | Bin 0 -> 3386 bytes .../19d0710b2aeacf4904cebbc1b304cbf02bad0d7f | Bin 0 -> 737 bytes .../1a024dc9c5d74085b76f8cad6600f4edc350b956 | Bin 0 -> 3615 bytes .../1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2 | Bin 0 -> 3615 bytes .../1b2437add9137fd1392126d2535573a016628d38 | Bin 0 -> 2039 bytes .../1c7a97739e894d39ece462a80f4039f3c778a3ef | Bin 0 -> 521 bytes .../1cac14fadaa7ae3640dd3916f3c78e3544afd00b | Bin 0 -> 986 bytes .../1ce3af082176f17eae5a3987ea9a131c74da45e6 | Bin 0 -> 3832 bytes .../1d103883a36101f8f67fd0eda2273177bd979069 | Bin 0 -> 3470 bytes .../1dba9107853637cddf377a6a07ca87c1e4cd18f2 | Bin 0 -> 925 bytes .../1e58390b95aa6e729013cd5ec6f67fd9410fe507 | Bin 0 -> 4096 bytes .../1eeae24b70a330001a18cb1d7b3e6358b34fddd7 | Bin 0 -> 1511 bytes .../1efe14c5799b31f2dc4c413643235c9ec5086e06 | Bin 0 -> 3715 bytes .../1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92 | Bin 0 -> 1461 bytes .../207778a53046b0f733160d96fc0e0a5f9d9f55da | Bin 0 -> 3642 bytes .../209164c30c53ba6c97e2bf6f767310e540f335ff | Bin 0 -> 903 bytes .../20f99df931bffe2e70b4114d50250cfa8c32ff94 | Bin 0 -> 909 bytes .../212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b | Bin 0 -> 3502 bytes .../212aefea1187a824be184640c2c673c5b85fb6e4 | Bin 0 -> 902 bytes .../21928dcf456992eb55399cd77f741a332978d73a | Bin 0 -> 3677 bytes .../22363c659b583272354f371c4d0107a0d2aff819 | Bin 0 -> 1165 bytes .../223d182dd2661a4ce650c9cff7f0dea8582b647d | Bin 0 -> 894 bytes .../2254a23660bd2a0ff02c837c37a270e59a460de7 | Bin 0 -> 737 bytes .../22721e338dad9836a391790ee54b4de0cbe00c89 | Bin 0 -> 3022 bytes .../227d4ae9ca9f113f16b84ab497ca26db8fc5ce92 | Bin 0 -> 3383 bytes .../234ff4cbcd44f84d9dc948795ee60452a0693625 | Bin 0 -> 788 bytes .../237565819ea32ff3cbad0947bbf63311e1b9a560 | Bin 0 -> 3403 bytes .../23af7fe04a1105a294ba962383a1a90895f23e0b | Bin 0 -> 690 bytes .../2465ecbfe1070f98fd88ca6158eb3014a19e01dc | Bin 0 -> 965 bytes .../24f2ed7e40f94ef359aa05060ee1d13ca5a26740 | Bin 0 -> 4037 bytes .../252954f3b81c2bf8a67fcfe0e3c1647f60993be4 | Bin 0 -> 1410 bytes .../252a34182e0b4b0f44f41e82de867242bdccea79 | Bin 0 -> 3994 bytes .../259e1c5b762116d55e5369ac45c611ee06f873da | Bin 0 -> 750 bytes .../262cc348aa328fa0e256c1ee38a13bf32be45080 | Bin 0 -> 376 bytes .../2640d5ce7a30e232909199583946b0d0e93639b9 | Bin 0 -> 3919 bytes .../265cf9b5e8b582233ee53de117a953ec586a129e | Bin 0 -> 3202 bytes .../2751bd28914df3bc80eabdf0a1722c01a9d9a0bb | Bin 0 -> 2058 bytes .../28459cfb1e5a27160fc0a2337bae96c1c7c0296d | Bin 0 -> 908 bytes .../28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2 | Bin 0 -> 3962 bytes .../28bb46d65faf3a8d3e112d25e7937e15571277e1 | Bin 0 -> 3483 bytes .../294892eee3e322937e5c48a692c1a80f512f86a7 | Bin 0 -> 3795 bytes .../295259cda114ddc75587c4237e42d2cb3bd58165 | Bin 0 -> 3851 bytes .../296b4a799ffd5949e625d993de20aaf47045b807 | Bin 0 -> 674 bytes .../2a74dc354366c2490747f436c3a9ece14330857f | Bin 0 -> 934 bytes .../2afe68d42826fa1cdad90848708c07a710658e9c | Bin 0 -> 643 bytes .../2b298d34dea054df52fbec818faef171c34e1c8a | Bin 0 -> 2100 bytes .../2b448ff1e24aa4da10783f03e86b58f5f8446205 | Bin 0 -> 738 bytes .../2b86a76cf1318e021a59f231a72bc64b410dbea6 | Bin 0 -> 902 bytes .../2c0ba9f07133ff5c9f25f2518a375ece8a4b2ab7 | Bin 0 -> 626 bytes .../2c25c12a76c3fa337df33fb8523855fef69a3552 | Bin 0 -> 903 bytes .../2c29b94d94502d8f305aad65c532f0e4ef6400a8 | Bin 0 -> 875 bytes .../2c673d0a67080d78b85738d7494270f4e9932020 | Bin 0 -> 3191 bytes .../2db4737507ab67ea548413e232fb8c5edfe907aa | Bin 0 -> 3332 bytes .../2dcef28430b5fefc918a951bf28bbf996dce68e9 | Bin 0 -> 909 bytes .../2e271373d7ea8184987d5d9cb61e0dab7b8af8e5 | Bin 0 -> 3401 bytes .../2e3b6c6ae461d3aaad63e918019874edd57bd40e | Bin 0 -> 1864 bytes .../2e7f99689d1ac0a28adf0785f28946561b3a9076 | Bin 0 -> 3826 bytes .../2ec2f6f5530b0daf769c3a5b608d95132283c248 | Bin 0 -> 3330 bytes .../2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a | Bin 0 -> 2270 bytes .../2f0c291ff5daa13064c5c7ff4a95d6785e78f66e | Bin 0 -> 3616 bytes .../2feba4853e4f4d64baeba180780940cdf8ff1825 | Bin 0 -> 3833 bytes .../304eea2da2a6032172159e9f43ddb21397a08224 | Bin 0 -> 1952 bytes .../30763ce17b7ec3d80954cf5a461743cf04238c6a | Bin 0 -> 737 bytes .../318fb04e83191ad61d152cc68f6d84d0a24a66d3 | Bin 0 -> 690 bytes .../31bd0841f052c324db7b6bcde7e5517b289708d7 | Bin 0 -> 3633 bytes .../31f779223bc6f44ef7a9a464fe11b31ca5abd5e8 | Bin 0 -> 915 bytes .../3286a72e23cd5f583a25bb5c489f12c60427d501 | Bin 0 -> 3964 bytes .../32e6b85afd36cbafcb3149b16da3783c5bbd8c39 | Bin 0 -> 1918 bytes .../32fcabb3daaba21acf21bad494ef03b3f81f7f7c | Bin 0 -> 737 bytes .../334532c6a6e2d134c489dfa4d80989fb06172d02 | Bin 0 -> 1027 bytes .../34bd03730328037405744586b88c57c81992cd31 | Bin 0 -> 3908 bytes .../34d566d2f53d0b428cd37a9a775992bc41763d9d | Bin 0 -> 3747 bytes .../34edfdaf9801227520aef18e911c0dd28cad2dde | Bin 0 -> 3297 bytes .../361bcd77ea202443741a8c6abe135f3d430c6203 | Bin 0 -> 3572 bytes .../36cc750fd326bb566cd107ddd157a6e7e191fcbe | Bin 0 -> 2917 bytes .../36d0151313a6b5053cb75bae03d3860dd48c725b | Bin 0 -> 736 bytes .../36e6dd737b0f9e0c28acd58660006ea5ba3e08a3 | Bin 0 -> 2254 bytes .../37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f | Bin 0 -> 3294 bytes .../37ecd40aaea21c8d39d36ded147feb60af7a58c8 | Bin 0 -> 644 bytes .../388e0215db4ce5142a628644b3cd431c515a1f14 | Bin 0 -> 2434 bytes .../389938579b67a293b6b5176c16e7199edcd75a12 | Bin 0 -> 2057 bytes .../38c4742b3533fb5fe2aa75661055614683a90b42 | Bin 0 -> 3891 bytes .../38d4760261ec36cb13967bed3bd2f1914082ade5 | Bin 0 -> 898 bytes .../38f482657361ba8058abba483509cec9b2ba7f6d | Bin 0 -> 3630 bytes .../38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308 | Bin 0 -> 3447 bytes .../3965ca28906687da44123bbaf6a6c589021a80b4 | Bin 0 -> 3201 bytes .../3981b84969aeaa457545577ff22b6fa973c21656 | Bin 0 -> 3325 bytes .../39a56836c3a816e0e4930846af629bdbd139e8a8 | Bin 0 -> 690 bytes .../39ab33714bd7e79f1905c2471643371bbd22b809 | Bin 0 -> 9134 bytes .../3a077a02dab98581d00d2f679def27b8818b9afb | Bin 0 -> 3155 bytes .../3a7353d5a43ca223422a827a480d3c7faf69c491 | Bin 0 -> 909 bytes .../3aa50d20cca6074a98c77480f27d62ef3675438c | Bin 0 -> 986 bytes .../3acf8c1831d6f97bdc31ff541fe1da11e558c37c | Bin 0 -> 4026 bytes .../3ae3f333e3883de4de59431f0bde46aaae04dc32 | Bin 0 -> 3374 bytes .../3b085660a48ed6743ab50e4cf21ba181487e834c | Bin 0 -> 3200 bytes .../3b240f61c01265600a3a37d2be9e1ba0d9e31990 | Bin 0 -> 674 bytes .../3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba | Bin 0 -> 1014 bytes .../3be80948934b8980f9f6a509062820245c51512a | Bin 0 -> 736 bytes .../3c185ac9221ffa389695a41ea1cd5d6edba6f5af | Bin 0 -> 1014 bytes .../3c3226c37487c643f0c392730627c0aef3ba1495 | Bin 0 -> 3271 bytes .../3c32698e2d5af52bd2011d3924058834f0a34ed5 | Bin 0 -> 1000 bytes .../3c6f5c00bc1086d604ae1a50eef96cf721c62353 | Bin 0 -> 674 bytes .../3c72b62ed35afc086b83c81e71053a0f4ef3988c | Bin 0 -> 3572 bytes .../3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13 | Bin 0 -> 737 bytes .../3cffa14e490c092657bbb33af7c14a33768b3beb | Bin 0 -> 3446 bytes .../3d63cf90bd396f0824b290f576997daf16884f80 | Bin 0 -> 3571 bytes .../3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0 | Bin 0 -> 1428 bytes .../3f67156ac8c46e96a0cf59c6b7f64af25316db6f | Bin 0 -> 3964 bytes .../40515498756f4fac616ddc3ac4c2669ea5a8771f | Bin 0 -> 3277 bytes .../405b2eaa9f8a6ec9aebcaa7d9897c1be18bf9b57 | Bin 0 -> 3783 bytes .../4073b68ca8908512aa7a9f71fad9866321690c5b | Bin 0 -> 962 bytes .../41b22775bbf5e9716b641b963830a1f35029b400 | Bin 0 -> 3297 bytes .../420326169b2a6c801a90fa1a414a17a461e81de5 | Bin 0 -> 4072 bytes .../4207635e571247e374c3bac2d5cfe6d279b3c182 | Bin 0 -> 908 bytes .../42ec8d96c8304cc2f4a98d1670752862ea967a5a | Bin 0 -> 3501 bytes .../433c4b6fa77655178d8d2782e9ac59fa527ec4fb | Bin 0 -> 3948 bytes .../43f38755fd9aeab3ac4f842c87379ea2e7c087bd | Bin 0 -> 1373 bytes .../4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8 | Bin 0 -> 3580 bytes .../44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5 | Bin 0 -> 1195 bytes .../453340dfa05d4c218067a9c01d12d0c0dc05872b | Bin 0 -> 944 bytes .../4589942d410d038d7739511c3fc862bfaf6f5d55 | Bin 0 -> 3258 bytes .../458e6fe51ffd10f4f003507da3d34105ff4ba41d | Bin 0 -> 3624 bytes .../45add649d95c14b12c577e21ae2af7f9050aaf64 | Bin 0 -> 1074 bytes .../45c53453a35ecd0c755c03936c68103b0dff17b8 | Bin 0 -> 737 bytes .../45e5a626f981cca5c160850cf0a7054d6dcb7252 | Bin 0 -> 898 bytes .../45f83321ca27fbb48c856bf051c5ac1b3293f5d4 | Bin 0 -> 909 bytes .../461ec2d1f3724eba0fc12a620a1a3b441bde50f1 | Bin 0 -> 3573 bytes .../465d2a8214142a177aaacafc8e7da3642b7410cb | Bin 0 -> 3570 bytes .../468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8 | Bin 0 -> 1494 bytes .../470813fb2b87e90fd61f1a3e3a7046afe1ca552c | Bin 0 -> 1194 bytes .../47a72fd0a7615521d4ced25c6df549288dc45418 | Bin 0 -> 3401 bytes .../48396ed7c8f8d7cb48705c22d157a43841e3bf54 | Bin 0 -> 3481 bytes .../48d0e70401c0f5124e8ee35ce51453c4648ea01d | Bin 0 -> 690 bytes .../48dbfc59064af6b303eaa6c6b39b92047b6e9a77 | Bin 0 -> 3639 bytes .../4976325a6b3d9d258b512743adf4dd7ef037ae4e | Bin 0 -> 4080 bytes .../49a3fc41e9dc84a4e693056bdfc96139d9f25f80 | Bin 0 -> 1229 bytes .../49c7e584495621defd79963151fb33ebf79bc35e | Bin 0 -> 675 bytes .../4a0a0cb71589d083291ea86ebc858f8a49868cfd | Bin 0 -> 3964 bytes .../4a0b77fa110185719de6c967c6030acab1ba82b0 | Bin 0 -> 4029 bytes .../4aa9b19fc0c44229c97649e98566b23235876c8a | Bin 0 -> 1073 bytes .../4ab06c821f1a0b5d761ecf299708867e4ca99e9b | Bin 0 -> 1016 bytes .../4ad50b5ec8b4abc82f90962f6d2a845720fc5b5e | Bin 0 -> 3879 bytes .../4afce9787aecf1f3bfccaf89fdf65cabb504b432 | Bin 0 -> 3615 bytes .../4b2b4eef9cb2f51ba3b06799c5dd384c7373f714 | Bin 0 -> 12560 bytes .../4b9f7e74269a66abf0332cef8d0754617fdbbd35 | Bin 0 -> 4036 bytes .../4bd18d873361567417de32972a3672d54102d412 | Bin 0 -> 1229 bytes .../4bd886ceae40aefd8e370a126f0c9eb914fd5178 | Bin 0 -> 3571 bytes .../4c2e48c4b70f93db36c76fde74b5a858f90eef42 | Bin 0 -> 953 bytes .../4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc | Bin 0 -> 3189 bytes .../4c7f90f4d64c6ef5968dedca30385c5cf76f3972 | Bin 0 -> 483 bytes .../4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479 | Bin 0 -> 3676 bytes .../4cdf29aab0710302590f972ae90c76ab98d4866e | Bin 0 -> 1041 bytes .../4ce91349ad2d273a481bcc859277322cfe3ca2cf | Bin 0 -> 1734 bytes .../4d8c1b4c5e122c2b8255b65e0bdb80ef9fa1573c | Bin 0 -> 92 bytes .../4dc96e80aeb3cfb40d59716db7316357a787ddbe | Bin 0 -> 3401 bytes .../4dedc9b74663d27cb122c6dc4d1f9de031bfba32 | Bin 0 -> 1533 bytes .../4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019 | Bin 0 -> 4096 bytes .../4e5ca638af464b9c18f96cf68ef346a1c7f4249b | Bin 0 -> 884 bytes .../4ea847253da2a1a1153634efa3d904a35c59f4a1 | Bin 0 -> 3462 bytes .../4f041d38c50cd4d7f6a65b8a3c0386ed8e62b97f | Bin 0 -> 3198 bytes .../4f04ca4460744c01566bd82d52cc7aad444d3e13 | Bin 0 -> 736 bytes .../4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71 | Bin 0 -> 1088 bytes .../4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9 | Bin 0 -> 2752 bytes .../4f9252d70faee72c6708fce7f5c744248fe3261d | Bin 0 -> 1800 bytes .../501d6d76ac062c912f5896543a7983bcf4253c55 | Bin 0 -> 3099 bytes .../5093bef091d961c4db1461031506e734374120f1 | Bin 0 -> 3273 bytes .../50ef30b0dff70dae8632b17cd493971d63a65ebc | Bin 0 -> 3544 bytes .../51a55b3718f12f1a65110f86eddf8f0c81ce148e | Bin 0 -> 3546 bytes .../51aa8cac7aa64345016927d1f2d694926244a183 | Bin 0 -> 2425 bytes .../51c860e1ee8f6b577aace2da887d1357df130b78 | Bin 0 -> 1132 bytes .../525b787309e65a8a02fd26b313f06598052a4ae3 | Bin 0 -> 3916 bytes .../52a4a908684553c648cecb1bc85476f72aec44e9 | Bin 0 -> 70 bytes .../52d54569aef7040df77bb0d484e929b927968c14 | Bin 0 -> 2753 bytes .../53fdf746a1ff4ca6004a67122c6667292ee01350 | Bin 0 -> 3259 bytes .../54097c70512fcb14a736ef5049279161b86b0a97 | Bin 0 -> 737 bytes .../54be5dc0bfab143c982bf41b88d21f0cbb4969e1 | Bin 0 -> 3888 bytes .../5598d89f542fdc4bc2bae890b3cacc9f41373306 | Bin 0 -> 673 bytes .../55dc2b5c70c3456c6ec3806f94d960d92488608a | Bin 0 -> 835 bytes .../5607123e29f461b258f5ba9bc32772766d09365f | Bin 0 -> 3447 bytes .../56484d61a742afd778d2f6c3d515aeebe632cf44 | Bin 0 -> 3775 bytes .../572e7a6444bf5587b2162daa9a72f1c8f5d51e9c | Bin 0 -> 690 bytes .../57414bd14950858020832e058d5df0e476472075 | Bin 0 -> 3427 bytes .../574b435b4ef7de4bcd68e660cb470bbdc66e374a | Bin 0 -> 1164 bytes .../5754da205d9819c7ea49216be19802eee8e753a0 | Bin 0 -> 4095 bytes .../57a964488d1e20c8533345f23beb1c5c9e01d449 | Bin 0 -> 1931 bytes .../57bb13e7806ca27917172cc30594672f9ba207b9 | Bin 0 -> 3737 bytes .../57c5d916bf10fdd126c0e96c1069369905b58cf2 | Bin 0 -> 1176 bytes .../583bba681bfd0c4f7716a1ce2d20c32dfe564d4c | Bin 0 -> 2171 bytes .../58cac50fb8d0c0a7fd30fea7c8f4b6eeb618604d | Bin 0 -> 731 bytes .../596704f5b04744871e34207f99222293839ff87a | Bin 0 -> 3200 bytes .../59ef60353ba39b1bc59b5a2b514d4a0ebce56a86 | Bin 0 -> 3520 bytes .../5a20733c310f3909b5a809efb0f46a8b5feae47a | Bin 0 -> 2293 bytes .../5a48db5a7daaf524abc694cd705d254a67422dd5 | Bin 0 -> 2251 bytes .../5a82000383e9b7b54a845b59252c45b3d5e033fa | Bin 0 -> 3648 bytes .../5aeb1c91ca68e775203bad56f26fd8674dc99fd2 | Bin 0 -> 1740 bytes .../5b74d4da2178f677bcbd74fff58b81d340f92e6f | Bin 0 -> 737 bytes .../5b86351af3b24a2417c722402ebb541f59f737d0 | Bin 0 -> 1178 bytes .../5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635 | Bin 0 -> 1991 bytes .../5c4fa075408244af7dd819c116c275fb3bfbb77b | Bin 0 -> 4096 bytes .../5c583e55833688cc4f7f6f425147ef3734ad269a | Bin 0 -> 1674 bytes .../5c843d345a3a7763930444707181aee5cd191438 | Bin 0 -> 3260 bytes .../5c94616c033d0ffca7d4d5a9a21ee506af3aebae | Bin 0 -> 4029 bytes .../5d7c621d353957c1f30ff0551bf103e0533ec5d7 | Bin 0 -> 493 bytes .../5d88975282d86be1605186c9f9390f2a97856f5b | Bin 0 -> 1443 bytes .../5dcf69ec2d27aa65a270aa75b893bfa843379c3a | Bin 0 -> 672 bytes .../5e196581924d733f8faa3d3619453aa01e3700f3 | Bin 0 -> 3882 bytes .../5e513e23df48329990ed63dc6310e820b21500fb | Bin 0 -> 3839 bytes .../5e541fdc01b0b57e4f642af19a8dcada95fc7af6 | Bin 0 -> 674 bytes .../5e84e44562a78a2ac27ff90e26bcc5a33835e331 | Bin 0 -> 3164 bytes .../5ecd7fa21205cd75112a2182955dc33dc1befd28 | Bin 0 -> 690 bytes .../5f2456ab7aa81a53b89e0af7455db660c54ac925 | Bin 0 -> 3447 bytes .../5f3f171c9d7370fc11a2d31925bfec08286dbaf5 | Bin 0 -> 673 bytes .../5fd69dd2daac7ec11fa9bc6789263ab658a5eabe | Bin 0 -> 737 bytes .../6163978844f3de0ffe06c5da0d2ac19d93a1a34b | Bin 0 -> 737 bytes .../6173cc33be71450af930872b0029d42f7f9a9e4b | Bin 0 -> 3188 bytes .../61e69397b08eef12ef32859936989b57525f163e | Bin 0 -> 3756 bytes .../624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c | Bin 0 -> 1426 bytes .../624e7bf21953e5ad0f95669086842161f2f86e03 | Bin 0 -> 1089 bytes .../6264654e1126813ba22fb14a3be0752b488fd418 | Bin 0 -> 4096 bytes .../6276b4e7495a620b384250f61dd5264698cc0a08 | Bin 0 -> 1243 bytes .../62a932027da8c0b8ab694b888aa2050de3883343 | Bin 0 -> 884 bytes .../62ac547e0a1d58293db58e3f3c23505b08029e56 | Bin 0 -> 1863 bytes .../62b7b6dde6cac1830d8d1b64c3ff146cc9ee909c | Bin 0 -> 3591 bytes .../63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a | Bin 0 -> 1073 bytes .../64382d709a4f6a87cb58fcccc0ad716207d409b6 | Bin 0 -> 1512 bytes .../64a109fad628c758f34cb85efb00dca77826b9f6 | Bin 0 -> 2434 bytes .../64d2d203ec77b22c80b0587a19bd157f609408b9 | Bin 0 -> 673 bytes .../650d6182ce2b79795477071a5edf71e5e4a2d9af | Bin 0 -> 377 bytes .../65232590b25ceebb4287ca8108142578ff4e341a | Bin 0 -> 672 bytes .../6539b554ad60eeffa97fa4024d2ee8dac1800a7d | Bin 0 -> 736 bytes .../65b1680687a0ba3ba4d53917b4a07a22f2b45caa | Bin 0 -> 3465 bytes .../65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561 | Bin 0 -> 3687 bytes .../665c6dc07ff4414425a77a786be26280af20851a | Bin 0 -> 690 bytes .../6682e09c97ef156e808ad63e3a5dd9030146153a | Bin 0 -> 3501 bytes .../669dfafe89414c0056ffa214d4ef4c1405d01c6b | Bin 0 -> 2202 bytes .../66ea20db9af412114e60b20143b063643ac0209f | Bin 0 -> 3765 bytes .../67201a0dcd94ff51530eaf8d43982203d8cc3613 | Bin 0 -> 492 bytes .../67740cc59121af29e2b57f491c6dfaf9e54a16f2 | Bin 0 -> 1512 bytes .../67c56ee635a2f54a05120f7f741b6de3b8416545 | Bin 0 -> 1266 bytes .../67ec3a092c013c1901c6056982c4b3c2d4345b12 | Bin 0 -> 945 bytes .../681a06e9ae918b77088a6c41e2084a7065fb4a80 | Bin 0 -> 3784 bytes .../68d08ed34adbab401519c4a6b457edf839a8e11b | Bin 0 -> 1806 bytes .../692e389e27b91478ee30ab6966720c8e42198b62 | Bin 0 -> 1195 bytes .../69301c0fab85b8afd0c235a97125acb36f259277 | Bin 0 -> 3615 bytes .../693212f1a1e378e4020ee13126b4ee8df4ce9262 | Bin 0 -> 893 bytes .../693a6ddbf67b0835d90ca231b9d68d9f2cccffbd | Bin 0 -> 3401 bytes .../695cb65aafb76161e3a319c68d4430ee80985b81 | Bin 0 -> 3313 bytes .../69a10fd0965617fda08b1ff2bf80999a51b8960a | Bin 0 -> 3995 bytes .../6a09a081020b1d5bdad5c981af10066d4ed4b045 | Bin 0 -> 932 bytes .../6a4404e833ba7eef96eec09b54978858661acecf | Bin 0 -> 3571 bytes .../6a5e936ffd7eba1efe6b7aa54b5beff373272822 | Bin 0 -> 674 bytes .../6a75638c3215e638e82bbc28c3fc523bda75f312 | Bin 0 -> 809 bytes .../6adf7477d929629afb4d07b4518a0e23b301b232 | Bin 0 -> 3432 bytes .../6bbd392cd841bb74dbba1190cab5066d5ecd9b2e | Bin 0 -> 3483 bytes .../6bdc8def26589304a945125ceb8bcb15b55d463b | Bin 0 -> 4095 bytes .../6c55036b8922e6b076ca36b92afa11601625e5af | Bin 0 -> 3395 bytes .../6c630175c87c742ab0c8723f6a0a53aae43b974e | Bin 0 -> 215 bytes .../6c651672e43ef4440abd90b3e6e1dd0a32e97437 | Bin 0 -> 3527 bytes .../6cb141671c7744c225aa3f7ce0e9813ae01f2a2b | Bin 0 -> 3440 bytes .../6cbd0fd179a77260e246c45f424a769b951363df | Bin 0 -> 970 bytes .../6cdbc5f074be9de313240590e337c7733f3bcb5a | Bin 0 -> 3572 bytes .../6d6212a5e12e69903e45291526bc0ecd3ea0e6f5 | Bin 0 -> 3368 bytes .../6d7de8f65158095884723fb0b1a4dd9bb1e4bcad | Bin 0 -> 3784 bytes .../6ed3b3793181c3319bacd290bc05190cfd944eec | Bin 0 -> 3570 bytes .../6efd3899822aa131578394f89fb5c8fd17d14771 | Bin 0 -> 674 bytes .../6f2c69f7cc2c99cb694c37710c7b46104906aff7 | Bin 0 -> 4095 bytes .../709b1199449d8138c4936b95179ba12fbb9a68d5 | Bin 0 -> 1496 bytes .../71050f1658866c73590296856c498f54087519cc | Bin 0 -> 1384 bytes .../71432178fa30339f80d4fe0b95ca40886ea4b864 | Bin 0 -> 3790 bytes .../715f569f1599e0fec12773fec26c7cc3cddbec4a | Bin 0 -> 3403 bytes .../7166e8b36a98dc10904f0a92bee9c729ef454388 | Bin 0 -> 943 bytes .../716737b5ca18f7589bdc492806e84bafbf7822e1 | Bin 0 -> 883 bytes .../71983e3b061a3211f83e36cccaf8be3d61e3ade7 | Bin 0 -> 2145 bytes .../725174c7260ca145c5513b1f8277581ad80d8066 | Bin 0 -> 674 bytes .../7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2 | Bin 0 -> 674 bytes .../7312c2e60d9d48602429f06752f2c1856b2484a4 | Bin 0 -> 2548 bytes .../73641c2c728554997a9a97544e207a235111d14b | Bin 0 -> 2093 bytes .../73786b6e81d47e740623eb11e031c685c239d8e5 | Bin 0 -> 2952 bytes .../73f63d7db6fb57a25e5f47a004e6f24eb66e685e | Bin 0 -> 109 bytes .../7454f672d5cea5dade5e712090b552ca39a3cbe0 | Bin 0 -> 3501 bytes .../745e5941c0812aa48b525e64969d6960c3f86d6c | Bin 0 -> 3294 bytes .../7460a3a91f807e0c47725fe6d856219c9b1a3f43 | Bin 0 -> 671 bytes .../7492e1899d22a15452e163881437a23ccc705d45 | Bin 0 -> 3162 bytes .../74f4656ef6630ddae9353e0989f10d9c8f37edb4 | Bin 0 -> 3401 bytes .../750e5dd452c8bc44976eae6b99463b951cf3ed20 | Bin 0 -> 3094 bytes .../75629895fd19a7ff9492e93a6d2aae0de33b6a24 | Bin 0 -> 1444 bytes .../75a37a2cdee4ac71d0996720b3c9adf50da186cc | Bin 0 -> 4096 bytes .../7643869fe4d74ef2e262015d55ea60dc08f072b7 | Bin 0 -> 933 bytes .../76ad1888b6ab0433924386fc74ec9668f08d3769 | Bin 0 -> 690 bytes .../76b77a87e73f5fd403af0cb73ad2b8bbcd572254 | Bin 0 -> 1636 bytes .../76f0e061914c0fe572963f0cc404d49121ec57a4 | Bin 0 -> 3325 bytes .../7757a4fcd5642fb0ac1f0230ced865a8546a9c29 | Bin 0 -> 865 bytes .../77a1114a47681f3f3cf0f65aa2f4645214b5c7c9 | Bin 0 -> 3826 bytes .../77aa55183550820d02557f4a09c688cfe6c2b5f6 | Bin 0 -> 932 bytes .../78623435559dd4f83050c3a5743c0652d2b47088 | Bin 0 -> 1616 bytes .../789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef | Bin 0 -> 2391 bytes .../78d330c46e50c13cae9560065fa4cc7bcac8dcb3 | Bin 0 -> 260 bytes .../790ffe47b5b84c76762f6b95eb51467844ef210b | Bin 0 -> 3910 bytes .../79153550be1dc1365a10a08792f49b02a9c56c40 | Bin 0 -> 3570 bytes .../79f2cafab7df9ff93fbd71edd2049f431f478a35 | Bin 0 -> 866 bytes .../7a13e0426d9dbdfeb38d83eb5a51d48e5de38913 | Bin 0 -> 4055 bytes .../7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0 | Bin 0 -> 736 bytes .../7a7c19fbe0835087aaa22bc29bc713d825a4853b | Bin 0 -> 3797 bytes .../7b1989a53e27b944b1f3a71ba37b95bf65502578 | Bin 0 -> 1228 bytes .../7b1fb1cf0c4afa24743bc18c43d810383ff35b5d | Bin 0 -> 3943 bytes .../7ba00c13f3af17b2f767423f969827ed237674f0 | Bin 0 -> 1014 bytes .../7baeee7bae72e0d0df2d314544e7476afffd9256 | Bin 0 -> 1738 bytes .../7c833d2738d69dd0303fd774e425c0da8da5b01e | Bin 0 -> 1071 bytes .../7cc04676ba336d7e15e837b9c7648e804b1b320d | Bin 0 -> 3200 bytes .../7cd0efd7b6d2fb98673ad3cf4b663bcefda82053 | Bin 0 -> 1094 bytes .../7d13671b71b0f71496a2e17bdc503826bd4d0c26 | Bin 0 -> 2270 bytes .../7d7637cadd57353b459108088ad62bd7746fca63 | Bin 0 -> 2554 bytes .../7d82bcecfa30a487dd52bd4dd8461304d7d499e0 | Bin 0 -> 1126 bytes .../7d8bfe2499bea27ee16d1dbeb1707037b99a87ba | Bin 0 -> 3555 bytes .../7db2e5e257d7891667d78cb272ca3ec3b6dc044d | Bin 0 -> 737 bytes .../7dbb31067130270f15c56b92f50d21818e4e817b | Bin 0 -> 4094 bytes .../7e1e374599e9ff2d515754b718b3e959966ac1ea | Bin 0 -> 3796 bytes .../7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa | Bin 0 -> 893 bytes .../7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca | Bin 0 -> 866 bytes .../7f6ab5401afb02d08c34b835ce95d4f886c50a86 | Bin 0 -> 3881 bytes .../7fd3e12d7776e72ea2a347d1a546f4e17275e205 | Bin 0 -> 986 bytes .../80003831f114e372c44f168f26e192100b8bc4c6 | Bin 0 -> 3289 bytes .../809b64143ccfb187a639440e8a49dc061733c571 | Bin 0 -> 1074 bytes .../81860583db2f2f8e3492dbe683063e2bc7c6a727 | Bin 0 -> 734 bytes .../81b11d6d83e00df6595eed84463b910f30d77270 | Bin 0 -> 3573 bytes .../81d289fdfa9a0ae60dcbe3b67db2b33db6159a62 | Bin 0 -> 3616 bytes .../81df12ca53a2432e288b18c6c00af52b8769182d | Bin 0 -> 944 bytes .../821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8 | Bin 0 -> 1816 bytes .../822f3b140b0934e8e0263f1dd2c6f1527c06df1f | Bin 0 -> 3466 bytes .../8259b1524f55bc4cb4f365ab450cbe984e494116 | Bin 0 -> 690 bytes .../82a1464e8df650fa1f2e4943d31904f6c266741c | Bin 0 -> 2222 bytes .../8305e70211c7966e15cc56bd12625ecb5f156ce3 | Bin 0 -> 1875 bytes .../8368d8b0cdaaba63b4183434b0a42567b4baca1a | Bin 0 -> 3200 bytes .../83cf3abf757469e3f081bf0714766a1d603dc2d0 | Bin 0 -> 2604 bytes .../83edd983c9817e0bd1a5613acab9ee0329bff86b | Bin 0 -> 1216 bytes .../84f9f1c8cf176949f562f077a36b81adbf8a2a1d | Bin 0 -> 3571 bytes .../8537957625c6fbe222a7aa318210d21a146ef206 | Bin 0 -> 3189 bytes .../860e128954a5d8933886313be553fb2bf872e6f5 | Bin 0 -> 690 bytes .../86674fe6d9cef4e7dc6f810214161701fc266658 | Bin 0 -> 3284 bytes .../8689c5a7abc8bab0ca468f15671d770331fa9a3f | Bin 0 -> 3702 bytes .../873fdc25def6c4c6fbed6a548d23f268c393be3e | Bin 0 -> 3614 bytes .../877637beb6b6884b7fdf7d01b07b5c950de56a3d | Bin 0 -> 4033 bytes .../87af0b01920985b125c1a5482d6cc9039887f624 | Bin 0 -> 3790 bytes .../881a7c422abdfd0dc71278d126ac94f22ae61832 | Bin 0 -> 1193 bytes .../89355b9199fa689195eeca48631ac8effaaeabb5 | Bin 0 -> 915 bytes .../8958860f8aae77703cc14b0ca88fa902319d4f1e | Bin 0 -> 3491 bytes .../89cbaec2af2c891586062633c097e9c4e9762cf8 | Bin 0 -> 3284 bytes .../89ce5fb7b86ce8f2c0e62b8fe79b12f9d2def007 | Bin 0 -> 3274 bytes .../89defbb1150e0cb3520e7510f0e7e06bf8973078 | Bin 0 -> 3501 bytes .../8a01471d4ddb4d5c1c71f89bb0018e9eb0aed463 | Bin 0 -> 2514 bytes .../8a962b1da16fd4b7af2bd08d0a1421bdcc3306fe | Bin 0 -> 3702 bytes .../8ae0eed9ec461f1b6cfa172573d0ff0c94d62f58 | Bin 0 -> 3949 bytes .../8b055ee2fc887c0d42c013c861a790b199cccfa4 | Bin 0 -> 857 bytes .../8b57c39fadcde2215b64ce3925654fba85c5ea22 | Bin 0 -> 1438 bytes .../8b9f236c2d33624817a2e03bcc8a3c78c4e756c6 | Bin 0 -> 3259 bytes .../8bb94ac9d58ce60fb4baab8403722f1a173497b3 | Bin 0 -> 3603 bytes .../8bdf4c52b4671f30500f90e08445da26adf93beb | Bin 0 -> 1870 bytes .../8c71832b8b6a2cd633d1dab36191392e08af24b3 | Bin 0 -> 3260 bytes .../8ce6863d4a91451041f82fb30a6bb6bcfe04bd57 | Bin 0 -> 737 bytes .../8d3d73f19d7bdfdcf299934f0c865d14fd0a209b | Bin 0 -> 1200 bytes .../8d5185ae5f4f9ec9753a995ca97c16f937508e20 | Bin 0 -> 2806 bytes .../8d5bca4e95a1b5f22533a680142064237957363d | Bin 0 -> 581 bytes .../8d66c97ec703bad66d714f8f76eaf3d80f4fec4d | Bin 0 -> 1041 bytes .../8d7451a7ce24c4ff1a684228fede21c6a27090e3 | Bin 0 -> 1406 bytes .../8da2fcb023ba27413d3e034b552e576cb348e6b8 | Bin 0 -> 737 bytes .../8dc032fd415972bf4ff2c700e875f05bf4c6708f | Bin 0 -> 2516 bytes .../8e3d1f50587b38d1b71c64cd1f047c4617ebea63 | Bin 0 -> 3746 bytes .../8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05 | Bin 0 -> 3296 bytes .../8ea73c00f324ec5a252b47857dd59f9828ccd400 | Bin 0 -> 3677 bytes .../8ed53379924ea04ec7917a8625bd8d42153516e6 | Bin 0 -> 3674 bytes .../8f555d98707e74734b2d9f175fecd508d9e73f59 | Bin 0 -> 737 bytes .../8f57cb63093021e5617344387a6ef9b472514e8b | Bin 0 -> 3616 bytes .../90c6b18f6c5042404ad9bd8a44dc7f3d079d3f97 | Bin 0 -> 519 bytes .../90d49e05c95e7e73df106cae3a0391439736a760 | Bin 0 -> 3938 bytes .../912f1e539eefdc5b24e0d1ea4733314c4a45dd73 | Bin 0 -> 3447 bytes .../919751352435a91c9e331722b0deb8b5a953eb17 | Bin 0 -> 3449 bytes .../91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3 | Bin 0 -> 3795 bytes .../9200f3939411cb47950bbc4578bbb8e061f17674 | Bin 0 -> 1088 bytes .../92f58505d1c1904cb7f5c0f38abf62432a380c92 | Bin 0 -> 161 bytes .../92fcc5e47daf5fc36a817aebef83191add2c783c | Bin 0 -> 737 bytes .../93416d9bae039bfbcd8a847cee630d6253b1c141 | Bin 0 -> 1968 bytes .../9379b70637beee45fa31d3e016363eefb5834488 | Bin 0 -> 3312 bytes .../938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc | Bin 0 -> 809 bytes .../93a0fefc5de9feda0a6e7130aea669a423920b9f | Bin 0 -> 2990 bytes .../93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d | Bin 0 -> 3501 bytes .../9458125f964837130e97064c97abb83f9646aa3a | Bin 0 -> 690 bytes .../948632bab2c87e14a502f6515527b4ce924f7253 | Bin 0 -> 3994 bytes .../94ea697bb35e030154ca5c901a1e3b3f39d36e2c | Bin 0 -> 909 bytes .../952698e57a900fd6dfd60cac5161b4acdb16b90d | Bin 0 -> 1229 bytes .../9546e93d1ebee30df46b3946a6739ffb52624e4b | Bin 0 -> 3571 bytes .../9626102a12051d367f2cbc10d134766302a2510b | Bin 0 -> 943 bytes .../96528c570cfaaea1ed945bba352f194fc4e9dd76 | Bin 0 -> 4041 bytes .../9671b1c78f584a5de5029ae5d2cbd807c4b9ff71 | Bin 0 -> 2118 bytes .../96d52303f3d71a4b80cd05cbcfeb0de94cdff14e | Bin 0 -> 3469 bytes .../96e04588af90d18412bed0fe821ee8609f1445f7 | Bin 0 -> 3784 bytes .../98a585cedac8d4736c292421597537dba155e731 | Bin 0 -> 3702 bytes .../99582e8bb92c8a66cd106db899de002e38a3f25d | Bin 0 -> 908 bytes .../997fc5a88d3784c7ca294afa083e0c803f801fb0 | Bin 0 -> 3571 bytes .../99b8f9912e5eb8b7305ebe14d09c80f21faf05cf | Bin 0 -> 3431 bytes .../99e5f2d8823aff6c698ecd0a2e0bf2a23f6f9f7e | Bin 0 -> 714 bytes .../9a2ecde2abf1b187b05d042840236f29c658f634 | Bin 0 -> 673 bytes .../9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3 | Bin 0 -> 3225 bytes .../9d5097026b59a1f6608991d745c001707134c98d | Bin 0 -> 17249 bytes .../9d66badf189ceb88b4a45d225c63a54787b9916e | Bin 0 -> 3418 bytes .../9d9923ec92568c981b160f715358aa70d8e079b2 | Bin 0 -> 3921 bytes .../9de75429028831dca2fd372a81cdd9a3ec343f22 | Bin 0 -> 690 bytes .../9f3c5c4568790eb1583d02d285d1a6bfc209e98d | Bin 0 -> 3882 bytes .../9f6f8fb110096b920fa6a3e65564ae0a0cca4834 | Bin 0 -> 3784 bytes .../9fc364fc3f2a6522f904ac7afa35f74853ff6cdc | Bin 0 -> 774 bytes .../a0235e7a5ff466220a742084c5c254c1ddbe9229 | Bin 0 -> 674 bytes .../a0753eaf3cf2571e61efa16bbd8ff494d1d746f0 | Bin 0 -> 4095 bytes .../a07942a046ea947ee7fa432c44f2dfe8369ad3b1 | Bin 0 -> 3208 bytes .../a0e018264482fdad568e31e3698ae48d09f5ede9 | Bin 0 -> 3403 bytes .../a0ed1be09750824c2f10f1e47249cea3210bf179 | Bin 0 -> 3571 bytes .../a130fb854ed6720458b564902ad8356882862daf | Bin 0 -> 3688 bytes .../a172350dffb276e420877c300b37260c243ef2d0 | Bin 0 -> 3615 bytes .../a19081ccc4eee7a72caf54666e34706bd6ccb486 | Bin 0 -> 738 bytes .../a1ff1dc066ae44ba884fa5fba82543577a5261ad | Bin 0 -> 3395 bytes .../a2158aa067898aba1b75e977192e03f13de20552 | Bin 0 -> 1229 bytes .../a22efd143aa1cf004a7ace6ba056dffdf1bed8f3 | Bin 0 -> 737 bytes .../a294bec7193e517c3d48201cd5ce2200a8c482bb | Bin 0 -> 1475 bytes .../a2f974cccbf5442bf1a8c55477afccf39168605b | Bin 0 -> 899 bytes .../a3bfeed2ef700425f8faf0c6b93295149f23ac2a | Bin 0 -> 3702 bytes .../a417315ebb027548f50a52b1e274fc5f8f6b0104 | Bin 0 -> 737 bytes .../a51278e710ef32f80c76a25419ded9f378f73928 | Bin 0 -> 2537 bytes .../a52b559cb5576d2d78315121b141ab72adb7bf20 | Bin 0 -> 945 bytes .../a55b4c066a0ade77b7d681e47b7341c479d68c3b | Bin 0 -> 3430 bytes .../a5b5d110779c03c88043f20cb31a443402cf401d | Bin 0 -> 1011 bytes .../a5c7daa6ba53a703f416d7f258ceb73a0697fbfb | Bin 0 -> 3294 bytes .../a5ccd3683d69f1699f62d1b25bb72bfe804c821a | Bin 0 -> 1229 bytes .../a647ad0e3689d42850d0dc5211b63ed3bbd51290 | Bin 0 -> 1580 bytes .../a6718d2e96c00ab472bab71e57b6ac3486b15921 | Bin 0 -> 3396 bytes .../a679b20b95835cea68864e84d9d5271dc148cdef | Bin 0 -> 3908 bytes .../a6a0b7158098709725de5a40691cf476af9fa826 | Bin 0 -> 1009 bytes .../a6c3e91a3a28655fce34b777ffc83112591a5305 | Bin 0 -> 3425 bytes .../a72e9c8f8a5898128d15f8db799805fb0af08769 | Bin 0 -> 909 bytes .../a778a560be38a3bd5a3ea923c350f804d1dece94 | Bin 0 -> 1353 bytes .../a7816bfa7527e483e56adb8c69bab7b1e8e9bd28 | Bin 0 -> 908 bytes .../a7960ebdd7568141959f4174078a227b67b6a42e | Bin 0 -> 3165 bytes .../a7f7698acb1a785bc16f01a9996a0b552feb9641 | Bin 0 -> 945 bytes .../a867840096cb79e3ce2a5d9484ce84f9477e3201 | Bin 0 -> 3490 bytes .../a8f7d1273ef6222a7d75652c9692146d1285fe98 | Bin 0 -> 3809 bytes .../a93092c6332f5da16c6445e9901c751967377973 | Bin 0 -> 1810 bytes .../a948c8df25bd48a0c09ec5a4c9414d75b92f9f53 | Bin 0 -> 1518 bytes .../a95561be75e63a4cbc50dc98ce9522df464cb9f7 | Bin 0 -> 1300 bytes .../a9c923edd522f91856371fb45fa87d4e432286c6 | Bin 0 -> 1444 bytes .../a9ffba3c720e1215a0e65c0952ddfda9664b2585 | Bin 0 -> 1011 bytes .../aa45f50d4ad0419c89f03c11032fefb7f27f09c6 | Bin 0 -> 856 bytes .../aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71 | Bin 0 -> 3487 bytes .../ac7d3c35fcfcfb6a3d02c4fc08f60981cb121664 | Bin 0 -> 3224 bytes .../ac7e3ccc463eb9334528b256bb2fa05b58274508 | Bin 0 -> 3180 bytes .../ac9900e115b00f2e3955371c512a5048cb9126e5 | Bin 0 -> 3615 bytes .../ac9c3021b430c86c30300143099b6f313a25ef60 | Bin 0 -> 690 bytes .../acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872 | Bin 0 -> 1445 bytes .../acd6f322d20bdd2325a0927aa307fdd4a57b1ce5 | Bin 0 -> 909 bytes .../ace9bdbbb130491029271f8a781605b940eb807f | Bin 0 -> 2203 bytes .../ad8e168bbba36c52740aa3bbb41d8f503715683a | Bin 0 -> 3571 bytes .../adc8f85e6d26d1d01ec10aa01b8733ec7622c7fd | Bin 0 -> 3842 bytes .../ae2a77d41b7fac3e56af9e15139c2fb667387445 | Bin 0 -> 3675 bytes .../ae9abebb13aafcead7dbd2a3b309be9bbc2ee055 | Bin 0 -> 4094 bytes .../af5ad09d790177794ac60e2e8cd54be03c7df970 | Bin 0 -> 869 bytes .../b02387538c10d919e45118d91ebb52d3fdfb74e6 | Bin 0 -> 3501 bytes .../b0b2cece76492218026f90503c4394daaa0d95d9 | Bin 0 -> 3572 bytes .../b1511eff332f93d93d5990f9d49014fbb8fc1a84 | Bin 0 -> 1070 bytes .../b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6 | Bin 0 -> 3572 bytes .../b1850b14ae80f8be2fd166838e994eb536d9a817 | Bin 0 -> 3720 bytes .../b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52 | Bin 0 -> 991 bytes .../b215c683e8544dc16c0285029b72f8ef8e4bdf8a | Bin 0 -> 3631 bytes .../b25fcfa7688e490ff503af7a1fe277c4ccae0e79 | Bin 0 -> 737 bytes .../b27898123afcd9087d724486b032b67f38f3b564 | Bin 0 -> 644 bytes .../b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811 | Bin 0 -> 3481 bytes .../b34dcdb2702d8fc829ddcc8908c227db8ab39f18 | Bin 0 -> 2570 bytes .../b38d66292459ad2fae16464f561aa199812b7ec6 | Bin 0 -> 1192 bytes .../b3a58509fdd22e3f6a77d4718b3933c2144e8be8 | Bin 0 -> 1810 bytes .../b4768e27463348cdc83824f609bcc0bc4c064648 | Bin 0 -> 108 bytes .../b47b7e03177dc00879c0c5eaa1046e289e8cc74f | Bin 0 -> 1935 bytes .../b4b6b38c2edab3fd1396696ab437c144603713be | Bin 0 -> 3747 bytes .../b4d11620cbd84d8f68d387969c7e1b6db5b437f9 | 1 + .../b50f8d1d0d99c5d7c8b8b185aef00d3fb082c567 | Bin 0 -> 3506 bytes .../b51cc11a839138e0a972e1c13b2da0d86e67a27d | Bin 0 -> 3520 bytes .../b524627a5d86fca25217970da5f8cb4c6119d226 | Bin 0 -> 3911 bytes .../b5709d7b4b2591636f8d80695dbf7b6a03ce488a | Bin 0 -> 3407 bytes .../b5ceea502c4b27e709a4baa0e2992cc942b57621 | Bin 0 -> 4030 bytes .../b5e84dfe2ad6dec21fe39b8a158022db050b7f18 | Bin 0 -> 3615 bytes .../b5f0a0ed4afb8db0be1385bbb58df0e39637941a | Bin 0 -> 1229 bytes .../b601dcb412a63b13ef14d9ae6c041acf7a7716a1 | Bin 0 -> 7 bytes .../b672eb91f36cce66d8e000551c6bef6d0215bfde | Bin 0 -> 909 bytes .../b6b132f06663996cf8c976cb44be9cfafbef83d9 | Bin 0 -> 3053 bytes .../b70773f3b09ea80a6adf9641ed753f364a1cb43b | Bin 0 -> 2541 bytes .../b711730ee7cf094e22dfed3d9bbdafe6537945fc | Bin 0 -> 1157 bytes .../b72f792402e28cf94c28bc8e33e785989e5683ae | Bin 0 -> 3674 bytes .../b748db1e3357fde15527e79c66dd5dcc3b96a07a | Bin 0 -> 1409 bytes .../b80c7961e196c01be618d2b46c9c3497f7f32c9b | Bin 0 -> 2481 bytes .../b85c172c80e31de442f8af7d1c182e0a88d4cef2 | Bin 0 -> 1409 bytes .../b8ab490b280bfa2e0514a86776e7c2d069e26fc1 | Bin 0 -> 3746 bytes .../b93163f45f4e7d49ee5721e5865aa2e7a394251b | Bin 0 -> 3401 bytes .../b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5 | Bin 0 -> 900 bytes .../baadac1b80a15dbf1db8ba42c4f439cbcd911828 | Bin 0 -> 2364 bytes .../baf11ce608a902568d00f98bca4ff7a819bb60b6 | Bin 0 -> 909 bytes .../bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7 | Bin 0 -> 3332 bytes .../bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c | Bin 0 -> 3189 bytes .../bb6db7d33c7d284a648fa1ec3b063027b85e4246 | Bin 0 -> 909 bytes .../bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55 | Bin 0 -> 161 bytes .../bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4 | Bin 0 -> 737 bytes .../bc72c2884450288e4b04aa3a04e632259ba7bb29 | Bin 0 -> 737 bytes .../bc82b67ead0462d088b02bc7bd2fc9916f522730 | Bin 0 -> 985 bytes .../bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4 | Bin 0 -> 674 bytes .../bd011a83422f5d64081ea5c6c9caf1224292ad42 | Bin 0 -> 3451 bytes .../bd466cc2cf72548409171797d3825e499c74a8d0 | Bin 0 -> 3407 bytes .../bd5f333b42d9e02433074109af2ed85120648125 | Bin 0 -> 195 bytes .../bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c | Bin 0 -> 2656 bytes .../be295faf55c0b0d81ae1ad6725c19e8910e3a0ed | Bin 0 -> 1300 bytes .../bf329543f2b0cd6f4ed335035294caef4853baf0 | Bin 0 -> 1830 bytes .../bf3afcd912f6bb94259c0892591fa1c90fab98ea | Bin 0 -> 737 bytes .../c01dc2df8abf8fa0da256c42671eb3ccef2c7583 | Bin 0 -> 1495 bytes .../c03fbdfcb8e959099df158b38e16e6e98fa0a8f1 | Bin 0 -> 547 bytes .../c12fd34002a04bef3844ea9baaa3afafc0b68f8c | Bin 0 -> 3642 bytes .../c1ec31d151af62da3c866eb4399bae3ea8fc9d4d | Bin 0 -> 737 bytes .../c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8 | Bin 0 -> 3809 bytes .../c262943ec79d2929acb8beab22686d0687c4427e | Bin 0 -> 736 bytes .../c2707301c99a3b7447cbc72f5bf9f2d133c66e86 | Bin 0 -> 946 bytes .../c27785bdba6f5e27bf38a51a58058998fe3edf8d | Bin 0 -> 1382 bytes .../c3324216917872b674aff6cdcb6f4aef27045523 | Bin 0 -> 108 bytes .../c4146e5fc9388f70a690f71722d86e7a38caa419 | Bin 0 -> 4096 bytes .../c49fb6353471694f0c78891efa2faf9f093c98d9 | Bin 0 -> 2123 bytes .../c504bcfb34d2cb10820c049d5437e9a9744b9224 | Bin 0 -> 1229 bytes .../c55fd6f979e9fe13ce89b4e236f40c4bd1bed862 | Bin 0 -> 1228 bytes .../c588d48045128b1d22de91bb640411cfaa4bc9ad | Bin 0 -> 3785 bytes .../c58f346547bdcb658ad1cb70fff078b8701dd117 | Bin 0 -> 909 bytes .../c676b7ee163f0a21bb6577d2649aa5d5cab305d8 | Bin 0 -> 3447 bytes .../c705dcc86039ee3a05d5cd15ab00cc2356d9aab7 | Bin 0 -> 2389 bytes .../c788bb2baf4eaccebbdbbd865fd36688103057cb | Bin 0 -> 3571 bytes .../c78af7af9a7f67ab59e314cfe67ca7825d697705 | Bin 0 -> 1688 bytes .../c78e5014d7ea4b8fcd106de5d889cec13d3d68e7 | Bin 0 -> 1228 bytes .../c78ece72bae26caf43d6739f97a17ed5dda5490b | Bin 0 -> 903 bytes .../c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89 | Bin 0 -> 673 bytes .../c915f6eb5bf85d6f906722e77e4ec28493ed54d2 | Bin 0 -> 3575 bytes .../c992a79f1c3f1f793885df808cb830ea934099a0 | Bin 0 -> 908 bytes .../c9ff9d69ff63ca545ec8ac2585c3c5202c2e552e | Bin 0 -> 3392 bytes .../c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7 | Bin 0 -> 670 bytes .../cac2b2aad6911e529198d2255be8f5fd47192152 | Bin 0 -> 3616 bytes .../cad08942d1b38a26085b2550c66de32fef4faa5c | Bin 0 -> 908 bytes .../cbab437e9479b87d3cc898a5db555d5cca59db3b | Bin 0 -> 3894 bytes .../cbc503f6dd40fdc5f03e8a90044cf183a595600a | Bin 0 -> 3867 bytes .../cc3c09cc41156962a002569cc7467bf10ef77721 | Bin 0 -> 3383 bytes .../ccd0c03acdc4430cbc759f3d672ff530c1d3ad48 | Bin 0 -> 3571 bytes .../cd89f3d76d270f94df4e98676711f9afddcd0a81 | Bin 0 -> 3839 bytes .../cddf422981522324fdb5b0b1a7cfe9ac0305e5b2 | Bin 0 -> 737 bytes .../cde1c623e7095e180c3a485bc8333cf8bee2e984 | Bin 0 -> 690 bytes .../ce6c351af3d3912d66db41de4a2c71fa812e8d41 | Bin 0 -> 3920 bytes .../ce93d2a149cdc6695256b062cfd1225092ba565d | Bin 0 -> 1131 bytes .../cea198948bc4ad0e2eeaf2ccf116d53c0c577881 | Bin 0 -> 3616 bytes .../cea7fd28eef6a02a13ea90d784c1207dded60b92 | Bin 0 -> 3653 bytes .../ced8a723d0468a850f5aa93642f934e547928f41 | Bin 0 -> 3448 bytes .../cf6f67c363efa2d77cdc6b81f6e74c9fc3e17143 | Bin 0 -> 3582 bytes .../d0288bf062576db0058deb80e6a475d6b1fdbc60 | Bin 0 -> 1846 bytes .../d032befc9c75ee26197c43f1d189c231d9aa824b | Bin 0 -> 884 bytes .../d03537cd5fde0747d593075d6a6f595f6a425a84 | Bin 0 -> 3703 bytes .../d03a3bf8b4d1976030d1584960ac3dea63e06290 | Bin 0 -> 915 bytes .../d058010606ec0a6c48817aa0d93a48e455e8c00f | Bin 0 -> 908 bytes .../d12a59b71ab1c96bada47b4a2ec2a6376699e344 | Bin 0 -> 3673 bytes .../d1788576205c4adf09461c7961a29a2b41fa9f04 | Bin 0 -> 2840 bytes .../d17b3b5c53b857d35787caf5a547e58e5a326f90 | Bin 0 -> 674 bytes .../d1b04032c449ccfdb320500ce922e905a9b746f6 | Bin 0 -> 3407 bytes .../d2c608fc637a44b7ab58dfbd2adfc919857c9a6d | Bin 0 -> 3931 bytes .../d2dc18b5d34852e1a4e1c9956d729259af11c024 | Bin 0 -> 1717 bytes .../d35b83a8f3a1503d9d8682d2e123127c42852032 | Bin 0 -> 3927 bytes .../d44d74d1e715b1eff600cf9025ccf7980cdbeb19 | Bin 0 -> 737 bytes .../d4826144f817a4419086d0c3e6eaf326843ab005 | Bin 0 -> 908 bytes .../d49261c056a68e3789b2aa041c9a8372f9342603 | Bin 0 -> 865 bytes .../d4ddfce77cf7f1e9b50618c636f9a811dbc64e69 | Bin 0 -> 1443 bytes .../d4e7f76de93312778f03a167ef99b93e8a277694 | Bin 0 -> 3425 bytes .../d50e0da5bd72f68d49bbe8b080dfe16587f9317a | Bin 0 -> 3414 bytes .../d5149852f264e96d3a7bfb87aeacf88e21d7cd81 | Bin 0 -> 3999 bytes .../d5278057d56703a1526dae2e78a40392f9d1a0d7 | Bin 0 -> 1845 bytes .../d531f5874372bc6af0e744859bca3eeb101e0d52 | Bin 0 -> 3677 bytes .../d54b651c80434d4c87f0ffc1a94a8934bfcbe57c | Bin 0 -> 1301 bytes .../d5a14089cae100bd2a22abd28263798e146743e7 | Bin 0 -> 1996 bytes .../d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01 | Bin 0 -> 674 bytes .../d5ed598cfe5995c9f93d9141181d629b5122efd0 | Bin 0 -> 1243 bytes .../d60a9a78b49e24cffcf407fe5fd50bb9365b4278 | Bin 0 -> 737 bytes .../d60b4797ac2c7cc376e670dd97ded488a75d7a02 | Bin 0 -> 3440 bytes .../d61f9163c366f3cb907570af9263cfe139523275 | Bin 0 -> 3386 bytes .../d62572b25b3b2f5d91a46757a7b98b5823d601a4 | Bin 0 -> 1219 bytes .../d62c0e1927c0518813dc457bf4b9798096758399 | Bin 0 -> 3615 bytes .../d799d28eea5dc9ec1b00e18d9bb650a069304d10 | Bin 0 -> 3571 bytes .../d7b49428ad8ba32ff3ed0de60bb2454517ad4318 | Bin 0 -> 737 bytes .../d80d720514be9459653d2eb637ea5b76c6982d3b | Bin 0 -> 3563 bytes .../d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b | Bin 0 -> 671 bytes .../d9533ed23666d92676c97620061e21a33d6d1bc5 | Bin 0 -> 1001 bytes .../d9d1d1a511c5a753ad80a380f28a4e405e73ca4e | Bin 0 -> 672 bytes .../da8789ba323501ec7ca492232eb9a0ab1fff559d | Bin 0 -> 672 bytes .../db1a0fcfb08514ca415b2009b06d4d03fa85d93d | Bin 0 -> 1195 bytes .../dbe1c29786bcb974e23eeeb948a094b8b60ed6bd | Bin 0 -> 884 bytes .../dc9fd88d1bef7f495ea968bc451988098eff8ee9 | Bin 0 -> 737 bytes .../dd0b7faae253e3f2d0251266ce65752648ecf3e0 | Bin 0 -> 3774 bytes .../dd0d01989ca202ed57067269b166148bc2c5575f | Bin 0 -> 3615 bytes .../dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d | Bin 0 -> 909 bytes .../dd8287ebeb79534ebe090d6085806f3b44fdfe30 | Bin 0 -> 3580 bytes .../dd8cf6b21f54ae0083050f5458e54b1dbc3180c9 | Bin 0 -> 491 bytes .../de0335436dd87366e3be8c7d728943a7c6177aba | Bin 0 -> 3920 bytes .../de66c31a968bf35553dff76e45831ecf1000856a | Bin 0 -> 673 bytes .../de98b3137af7eab1edef6958a79ff8d731056f01 | Bin 0 -> 3478 bytes .../dedfa96557b62d4a8df63694dad15e0b0f491303 | Bin 0 -> 737 bytes .../df2d4210d382ad94c550c3d560c607c8febd8294 | Bin 0 -> 738 bytes .../df314bab00b12c1a31e29132d5eb9771ba14edc8 | Bin 0 -> 3438 bytes .../df58f2b01e1583f71599e1e98f5c8cb50fee4cf0 | Bin 0 -> 4096 bytes .../df8361ab66b111e870d66da944074034a8b9aff0 | Bin 0 -> 908 bytes .../dfa5eae13138c3035d5be8ee38d14437664b8099 | Bin 0 -> 1109 bytes .../dfa62f0edaf6b90d9fa8d58b3792abf1937db679 | Bin 0 -> 3427 bytes .../dfcb7073dea2e606dc7b1877577bbaac9c020998 | Bin 0 -> 3823 bytes .../dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074 | Bin 0 -> 903 bytes .../dfe4cc06c05e43dbedb195bd5b3e5d2cc889ab1e | Bin 0 -> 20 bytes .../dff8677490e8b612a3fa1aafea7db76a57531a7d | Bin 0 -> 674 bytes .../e00c632f0217269fce83f0baac055b2e9dc522d6 | Bin 0 -> 3402 bytes .../e04df2a864a3be5065d25603a6f79090c8f70ef8 | Bin 0 -> 4094 bytes .../e1fc2e3105fc3a2a7be7d48d8edce0632572a88b | Bin 0 -> 195 bytes .../e25a7b9befe26a89d379fecf190f4b9aad7c2305 | Bin 0 -> 1644 bytes .../e2d7108a4559fe36b7ff8854d7cf96549deb8897 | Bin 0 -> 1444 bytes .../e31c99618df1f322012029dcc2e0f1d4fd4c3977 | Bin 0 -> 3605 bytes .../e33830dba87718ca367a275cf4c7a59ccd4927ec | Bin 0 -> 674 bytes .../e3f7aeef652e35f920ed3fb6081884f12c9f9bcd | Bin 0 -> 759 bytes .../e41056775fb1db9c520347187e5f33b529db14cb | Bin 0 -> 3277 bytes .../e46cf6de573e5e07b5e2429ddca6277e5dad9b4e | Bin 0 -> 3808 bytes .../e478fba23e6bec21363045d0d1de05237a0dcfe0 | Bin 0 -> 1227 bytes .../e48eb2509e260ee8d19ebc618b895a457491c583 | Bin 0 -> 3933 bytes .../e4d71e3a91460379358500d9b998a911e04f0bd8 | Bin 0 -> 2270 bytes .../e4eec0bbadced0366353f387512000ec8504f501 | Bin 0 -> 674 bytes .../e51409d12b954c9e7478e79b1393b76c3dea5eeb | Bin 0 -> 1074 bytes .../e567be3c710068e4b985312b5c342e78ac177111 | Bin 0 -> 1230 bytes .../e5a85219718efd390ce1cffbe60cbb8fbe7bd07d | Bin 0 -> 1216 bytes .../e734d584122a869a16a10dd58fd90b82e8c9f444 | Bin 0 -> 909 bytes .../e74c6de58f2b27059af669fadc1c6e65fc5c2c6a | Bin 0 -> 642 bytes .../e764ee13b2cbee6650ac9a43e30059748be94875 | Bin 0 -> 3701 bytes .../e78589cd285cd5f51be25c22e99ee6d5b3dd0fea | Bin 0 -> 787 bytes .../e793e02598daa45d72386d500fadc7b8847966ac | Bin 0 -> 2240 bytes .../e7b94d5f17cb2bda3a289528baa04e66b5ef5478 | Bin 0 -> 672 bytes .../e88137978a989ffac6c11e5565b1678e3a2f2a07 | Bin 0 -> 2319 bytes .../e8baf78fba26327aeea9353f4160469133c9e26b | Bin 0 -> 1220 bytes .../ea76c818a4ae9c92d431de82f50c194727e99d9c | Bin 0 -> 3274 bytes .../eac3471325184b407218efb4fbf9ed18502b90ad | Bin 0 -> 690 bytes .../eb0614a6bcbfbf345c2760bc22ca0061c5d6e670 | Bin 0 -> 3492 bytes .../ebd0214511a49a39219400618c3d355021157884 | Bin 0 -> 889 bytes .../ec6ed05526c37da3cb8f5f13c4af297999ac86b1 | Bin 0 -> 1147 bytes .../ed12741b6e328f435f5859366b7307de25191d84 | Bin 0 -> 690 bytes .../ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2 | Bin 0 -> 737 bytes .../eda54f7e9fa02af74383bb89950adf6dc3d55401 | Bin 0 -> 3888 bytes .../edb8eb2806f70ced44e984d5b6ba736e2bfc87a6 | Bin 0 -> 675 bytes .../ee4553a19b0f86ef2b74c1d2821b9be12bf19190 | Bin 0 -> 3403 bytes .../ee9397fa6666c21dcfde633a790ae8c928e34f59 | Bin 0 -> 3962 bytes .../eef3168490e70c8b410a8595d440d05ebb3265ca | Bin 0 -> 3751 bytes .../ef08605ec2c45ae9d761fc90ea46e73328c81b2f | Bin 0 -> 900 bytes .../ef10ddcdd49df604183649b612ffe27ea1473786 | Bin 0 -> 897 bytes .../f030612c62ffda07dfd3f71da34a355f810351c1 | Bin 0 -> 690 bytes .../f044a49ce9380a26ab8ab4b92999c9d045fde573 | Bin 0 -> 279 bytes .../f16469af68d82405182616d57cb88e79a8f84fa5 | Bin 0 -> 690 bytes .../f20d61a351628b54d7acc53df3fa9a8b89d23a35 | Bin 0 -> 674 bytes .../f279591cee3d393edab74b64f5bff2783f7896e1 | Bin 0 -> 1104 bytes .../f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3 | Bin 0 -> 3809 bytes .../f2fcc44bdba89769aef1a58d9067e5e43918e9c0 | Bin 0 -> 3465 bytes .../f32305c1d36de1b0fb6d285af73faf95c35dbd16 | Bin 0 -> 895 bytes .../f35d6f2a1afc32377a077202b533490fa53ef4e2 | Bin 0 -> 3826 bytes .../f45c5268333bc7bb0b7cca415d591d825e42ceb0 | Bin 0 -> 673 bytes .../f46c909f402c6c9388a03588a3259caa870ab286 | Bin 0 -> 737 bytes .../f490ddb2112392be3524baf6a9232090865665e2 | Bin 0 -> 737 bytes .../f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9 | Bin 0 -> 737 bytes .../f4f2510033775e469a30abcfbc0a32fe6d515f8e | Bin 0 -> 675 bytes .../f4fd47fe28b86db86a6924d755b21e4de999097a | Bin 0 -> 908 bytes .../f56b7a7c163e45f1bcb7f770f1dedae14f6118d8 | Bin 0 -> 704 bytes .../f5dfbb265362ba53aba22dba5f1ea72fd6e5944a | Bin 0 -> 3964 bytes .../f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae | Bin 0 -> 3601 bytes .../f6913522dd421f05632968344bd38c06d1954d4b | Bin 0 -> 3403 bytes .../f6c8c28942664fd860f1105fc6a734f94a6f84fe | Bin 0 -> 674 bytes .../f7048f702c3ca6c9586dbb81db5bf4858dcda2f6 | Bin 0 -> 3943 bytes .../f734fc3f014d55431bcdd133b58da2b1a96380d3 | Bin 0 -> 3501 bytes .../f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9 | Bin 0 -> 689 bytes .../f81cb544d394ef24caab41b1d9fc7108a95ceb1a | Bin 0 -> 3484 bytes .../f855d4851bf113baf924a3694e3256fa084b060a | Bin 0 -> 3571 bytes .../f99f314fc629fdbb8ef0abbfa2b1315f081c66aa | Bin 0 -> 3168 bytes .../fa3a1b5f04942ab0eccd31075514dc93e542e090 | Bin 0 -> 5 bytes .../fab4991ad6fa8f169113266acab7a163ad17fe21 | Bin 0 -> 1715 bytes .../fab7c6b18d19dd33b24adc9cf45d53e385ae502a | Bin 0 -> 2186 bytes .../fb0317a7ce975c9dfa03675f67ca79aa488e3c31 | Bin 0 -> 3615 bytes .../fb9480b786a21506a1ec7934c939acf52c7bbe08 | Bin 0 -> 3502 bytes .../fb99ad4d6f7a231d56480050b364e0e37e91f80b | Bin 0 -> 690 bytes .../fd86260d8b505b81449a6c72f4c86ae869366afb | Bin 0 -> 1228 bytes .../fdad067c8148822fffbbf2e8ec8b0021ea597b5a | Bin 0 -> 673 bytes .../fe9abe3ee8ab25893f43f213496ba1c01f9d8579 | Bin 0 -> 750 bytes .../feb7e9ac7b76f28911465a514c2c8ec273e2ba60 | Bin 0 -> 17461 bytes .../ff7ba21b79ba75d821d722933b5d03a1437c38f3 | Bin 0 -> 3848 bytes .../ff7f5fcbaf508db2e56ff22d5f38446f03837749 | Bin 0 -> 674 bytes .../ffc9310b8efa4d9644324dc9c79b0024aa28c561 | Bin 0 -> 1732 bytes external/boringssl/fuzz/minimise_corpuses.sh | 44 + external/boringssl/fuzz/pkcs8.cc | 38 + .../129ebe4bf8b167a37741c9c470fd7c4a0359ad63 | Bin 0 -> 633 bytes .../1bf03b5d9f129cd80513b820a55c9568eb1d350b | Bin 0 -> 122 bytes .../225df81ad5fc9783575b57e20207645e55a8fa3f | Bin 0 -> 137 bytes .../3033b336d833baef80981f40394c281c20677f53 | Bin 0 -> 691 bytes .../31aa87887801ac3f6eaab0bade714e56fcb5fab7 | Bin 0 -> 528 bytes .../3f7e0b4378403f44de34874789bce582790a1348 | Bin 0 -> 185 bytes .../40d5a9f71cacb2389b58a8a24cfa52d6b51bf046 | Bin 0 -> 241 bytes .../57e8e625f2f2313f2ec174a3209972e9bc5125ab | Bin 0 -> 149 bytes .../89db3807a0d30e36007b74c8ee4aac912fe3fd75 | Bin 0 -> 1304 bytes .../d38e79992de4ffaf585a6450ba2e6f21188fdd08 | Bin 0 -> 335 bytes .../d9206dbdd26c06ee8de4e587553e72b3bb22d36b | Bin 0 -> 344 bytes .../e0a0b34deb64510a36919a13258bd2c8725e41fe | Bin 0 -> 146 bytes .../e5cfb9f3e23eda47731b1cf3414df1bd408179b7 | Bin 0 -> 78 bytes .../efb2c016e9375355e04a5d99e2a17415c9d4f648 | Bin 0 -> 66 bytes .../fc0fad9f9fb142dee99a03a50a64d10767f9f18e | Bin 0 -> 381 bytes external/boringssl/fuzz/privkey.cc | 21 + .../00c42569d947a510cf9797c6f57e072aa0ca5bb3 | Bin 0 -> 2013 bytes .../015681c081de9b2950dcfe212a3ce6a12cae5104 | Bin 0 -> 615 bytes .../019773b072a48b8cf7e0aa11b1d9a37898dc70f9 | Bin 0 -> 275 bytes .../040e09a6e89086dfd9260699f1dd27f1ac8fc608 | Bin 0 -> 48 bytes .../05025c1927ae0e2827a85a34c295f2aa08e58b67 | Bin 0 -> 559 bytes .../05a573fb3bb39c31923a303fc2792e72eff61cc4 | Bin 0 -> 561 bytes .../061a18d5264822fc83ec032231ebaf117ffb6b35 | Bin 0 -> 250 bytes .../0769477785fe09940b3003c2d57ae2510be249d2 | Bin 0 -> 249 bytes .../077658aca2047636d0a66aff776af558a960e60b | Bin 0 -> 275 bytes .../09a98dfe76a481a565719e05e80fd48d780144bf | Bin 0 -> 102 bytes .../09db9192b630c602121231a0de852de7888af92f | Bin 0 -> 118 bytes .../0a6ff602ee335dd5e91e1ce4e4807f9830108e4f | Bin 0 -> 597 bytes .../0b274245377b1f87f39f76dbc876d43192ec7346 | Bin 0 -> 381 bytes .../0b85f3e44876a3d970e21d829336e33faa9d36d5 | Bin 0 -> 872 bytes .../0c49b71767b49200648c3672ba14308d8a525961 | Bin 0 -> 134 bytes .../0ce90fa3fde09714028bbed4b835b9889868f05b | Bin 0 -> 152 bytes .../0da750195873f5330d846c55736fa9c952daba74 | Bin 0 -> 45 bytes .../0e33f8a77a50c72a6a6d72a539badee3bb8cf95e | Bin 0 -> 1574 bytes .../0e371858c1ec53ce2327b9067fb0f663b3951f2f | Bin 0 -> 232 bytes .../0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff | 1 + .../0fe7d2c6759892ccb8117dee4427b01230c32ac0 | Bin 0 -> 275 bytes .../111513715bade1f0f1a1bcd76defc32853664673 | Bin 0 -> 210 bytes .../1116b7d25a60b231dcb7f6b244cfae6ebc272bc4 | Bin 0 -> 503 bytes .../144955d4b56923a5003f4778a724aaae45e133a7 | Bin 0 -> 1193 bytes .../159042d0b44248e2218fde21764132a20b29f794 | Bin 0 -> 365 bytes .../1716744626b9a81aafcd612d6802ba6d968533b1 | Bin 0 -> 365 bytes .../171735592c8f147c39aa928c10b3a2fb101eadb1 | Bin 0 -> 134 bytes .../1786f7578e40c0526ef27e9d14276f2e30cf1fa4 | Bin 0 -> 133 bytes .../17960a325cbc94a0d43d005a00f7243b44403574 | Bin 0 -> 381 bytes .../19793a06cf885b10b04e38a23649bd7f1e31301b | Bin 0 -> 134 bytes .../1a23c272e3bef73eb0bbd4f74122a1c99d86489d | Bin 0 -> 277 bytes .../1b2547c6637c3b54fe2c243a56ebc2b778e574fd | Bin 0 -> 279 bytes .../1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b | Bin 0 -> 232 bytes .../1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018 | Bin 0 -> 134 bytes .../21390a583c6914c6217e3e7a6f0f500565c3db01 | Bin 0 -> 215 bytes .../25c8eb80d13e90627aeaeb6041ec5c9c80db73ef | Bin 0 -> 745 bytes .../2658121eaf30eacfa090bbfb248068dde890a904 | Bin 0 -> 503 bytes .../290126ecf71a6a446667ef8d55e533330409423b | Bin 0 -> 593 bytes .../2909caee653dbeefc20c7071a91eae9f4cfa35b8 | Bin 0 -> 381 bytes .../290a2847a0a316567c9c292d1655934b092196b4 | Bin 0 -> 275 bytes .../29c333dee5bb24eebdd3a69e2f384115b62f5da9 | Bin 0 -> 247 bytes .../2acf5bdf834aaad09ced02a2f9b17c6b84ee183e | Bin 0 -> 413 bytes .../2b3a1c22ead8fc7d963fc8b09d733529970a1ed0 | Bin 0 -> 385 bytes .../2d4091ae2ed10fe2008a9345042316e0d9e12f78 | Bin 0 -> 56 bytes .../2d91275a1b8cfa0d6d96bf496b71f39ee061f696 | Bin 0 -> 440 bytes .../2eb06460c0ce9f89df1b7b71d59ffe29007b24b9 | Bin 0 -> 381 bytes .../2f180fb11e42c282af2cce12419433c3edc37274 | Bin 0 -> 133 bytes .../2f8e198fa3cd2d59a1bbe2ac182de095368689f9 | Bin 0 -> 365 bytes .../30cdd0dffab35c6e1fa833a06956f29de0540164 | Bin 0 -> 448 bytes .../30d35fe2026932f96aa4254f12fba48d42ddabe4 | Bin 0 -> 108 bytes .../312b84ddde85711337fe7e38f9e66c67d53af068 | Bin 0 -> 857 bytes .../32d0205dcae956ac26c7faa7a5696daaf288ac83 | Bin 0 -> 515 bytes .../32e6213837aac65804f3b3c57a9a58b3dd751e29 | Bin 0 -> 596 bytes .../339e070bfd090281e546cefa960412b76bcaafb0 | Bin 0 -> 372 bytes .../346b0e49695097dec5bc9f39616b744e825c32af | Bin 0 -> 52 bytes .../3485d5bced3fb725b0d5db9a9a5ededd07b84b39 | Bin 0 -> 60 bytes .../3499daeee13c1a1f32021dd6666834b3f57eaf75 | Bin 0 -> 1269 bytes .../35191613835734a77f62636d0e5ca55656df19ef | Bin 0 -> 121 bytes .../35d56dec4d0b9eee7bc3f7116694b78bd3e14adf | Bin 0 -> 134 bytes .../35ec32a0302aff2dd46b92744dd0e0aad643a735 | Bin 0 -> 365 bytes .../390356980b48356de3bb28ddbc5cf107ec4f7a85 | Bin 0 -> 614 bytes .../3a37605591ee36af41d000670302ff871c78a9e4 | Bin 0 -> 652 bytes .../3b99bd1bf571734f599661c6e3032034c1c397a7 | Bin 0 -> 150 bytes .../3c0fd6b8973aecbc8515b7659c611b1f43fc9512 | Bin 0 -> 413 bytes .../3d70c8546bd266eb21f3ad3410ce40ce0f11c754 | Bin 0 -> 1422 bytes .../3da8eb8c3fad53453fe6be874706f011290cc193 | Bin 0 -> 385 bytes .../3fa9a81502da9188dc226556ca3ebedf247b2a31 | Bin 0 -> 605 bytes .../401ae4a9be451bec291b1ea4d2a3326b9b40574b | Bin 0 -> 134 bytes .../4084d7b10c7f3c7e5312e49c478ba7f01545fc10 | Bin 0 -> 134 bytes .../408eb93771f2db1955f2d3b886aa1288955e9595 | Bin 0 -> 46 bytes .../41180009eff3da207f5fab3a1e03764aaabff217 | Bin 0 -> 149 bytes .../4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5 | Bin 0 -> 245 bytes .../435a4c85a2ac1876353838fa2a6ed505b0513fb6 | Bin 0 -> 148 bytes .../48832cec638db3098a957580a1da162535ae25a0 | Bin 0 -> 366 bytes .../4af1489b0c9ee9d122721c257dbcc71076950412 | Bin 0 -> 211 bytes .../4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db | Bin 0 -> 135 bytes .../502f53c70c4a0cdc28ec7d4e5e663d71628eba04 | Bin 0 -> 268 bytes .../50bc50a6a7b81c4f8056973b0c54bdae838c2e28 | Bin 0 -> 231 bytes .../516282abddff3db5f7806bb9540c4ffb3da5a647 | Bin 0 -> 133 bytes .../51911d8d5529737e78a8c07f7835add996096e4e | Bin 0 -> 1592 bytes .../528fc66881a989e0be226cb9681f25fe8f8639e8 | Bin 0 -> 567 bytes .../5519002b1f0f5920ced3f7db347bb2a9a803f13e | Bin 0 -> 364 bytes .../552b2592e9e09483334a9e43fb11cf4c60c9a040 | Bin 0 -> 232 bytes .../57e60fab45178a0597b816ff92a5f72d6c789da0 | Bin 0 -> 502 bytes .../586d7d93d8c2a3f43248c6b437e743de6dc0ac6c | Bin 0 -> 364 bytes .../59685ccee38382c2b951f3f147a930aca6157cc9 | Bin 0 -> 425 bytes .../596f5f7d381c904a2f4bd12ec6e061b8e9656287 | Bin 0 -> 220 bytes .../59f333ce69d71f603fe0864944d9b5da92b4cf87 | Bin 0 -> 134 bytes .../5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36 | Bin 0 -> 279 bytes .../5b1101cb6a5041a87b29734f0a9e5db654781ad9 | Bin 0 -> 248 bytes .../5b31b569e17276924adb39d7c501f8146eb40217 | Bin 0 -> 132 bytes .../5bacad39834b363e5a1c70862881bf1bd6cd692d | Bin 0 -> 1193 bytes .../5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e | Bin 0 -> 250 bytes .../5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e | Bin 0 -> 708 bytes .../5d50b7105a65869ceb68ad2a8d6dbadc184d0841 | Bin 0 -> 1192 bytes .../5e89654d60cffb7a5a715535a4aaf4828269cfaa | Bin 0 -> 210 bytes .../5ecdfa9f5c5f4052646bc85523a3d66f606f050b | Bin 0 -> 246 bytes .../600e8914f660c5e8d5d403313e6d50c022e60bec | Bin 0 -> 604 bytes .../6099440734ee930046e454c92ff576aafe33023c | 1 + .../61db53da0168c52fbe159f9490f899d40babe9b8 | Bin 0 -> 701 bytes .../63a1c254ef76396040a8a11c9715f0d7435ca3cb | Bin 0 -> 307 bytes .../63c16bcb66f7e1bf859ddb2652033d08322e1ef9 | Bin 0 -> 364 bytes .../63d06cb1068c254e3dd462b434e985ae8fb10e9b | Bin 0 -> 135 bytes .../63fcd39ff8f3d87e84282915540cbf08e2df0d7d | 1 + .../6457f1ad199e3535c56189326f5785071ca45658 | Bin 0 -> 223 bytes .../64d5fbd143dd252a45201c7ca8a9d5df6503fca3 | Bin 0 -> 364 bytes .../6564b23ca877f7b46600c0628d9ecc503888cc67 | Bin 0 -> 230 bytes .../69568bdb90b3dfaa1537da561b1fd3da443c4965 | Bin 0 -> 274 bytes .../6a291a3d2db8f217bbf4778ff04b7f09c8fb5308 | Bin 0 -> 275 bytes .../6a3f0dff7e9cb30114ba47d280dc228074a3884b | Bin 0 -> 366 bytes .../6b470afcebd759c96b6c15f6936f8d3068eb79f1 | Bin 0 -> 685 bytes .../6fd9b893b202e88165bd8b4b0e55b2879667606d | Bin 0 -> 125 bytes .../6fdabfc555764f5a61263c6c213e57f93fb12a0b | Bin 0 -> 233 bytes .../7019dcba7ca33cc061327b124fb24709299a3e9b | Bin 0 -> 232 bytes .../704cc64f5ba905eeb3f4cb8049231ee97c34e4ec | Bin 0 -> 178 bytes .../7115008ca4af946a5e2cec6166c8cf2bfacf6f0b | Bin 0 -> 133 bytes .../715d34e2a6215569029969826e0bf2b78534fc14 | Bin 0 -> 133 bytes .../723b16d087e14eab86b59cdd487a264f91cfc4e3 | Bin 0 -> 1422 bytes .../7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10 | Bin 0 -> 339 bytes .../74de715f42ee6e07b7b86bbe56d488227e0e30a7 | Bin 0 -> 231 bytes .../7508d58d4f00dc14a072ef68c79d5db942195bac | Bin 0 -> 216 bytes .../767184473ade3f29a1a06a6498f9acf4aead72ea | Bin 0 -> 276 bytes .../775f54fa88dc085283d4363426a4c408771545ec | Bin 0 -> 364 bytes .../7898b0d86f7cc71b934347a20e134169ef076d2f | Bin 0 -> 134 bytes .../79959ffbd0c540e1769f94f6381bbd2c28736a86 | Bin 0 -> 857 bytes .../7997306479d844e94a2b8cd0c33bd928bfaaf26b | Bin 0 -> 408 bytes .../7ad800c3d44252093ad9ad6030f08a48fcd72f70 | Bin 0 -> 648 bytes .../7b1d3464ee005c28e177b4f65f7f71a1cd50462e | Bin 0 -> 277 bytes .../7b4202b35800a1c6fbfde9de8dd7c06704353bdd | Bin 0 -> 57 bytes .../7baa95845eeabd342bfec6eacfa14a623c59e158 | Bin 0 -> 103 bytes .../7c418f677717e6525bc27159e3af3a5858b15018 | Bin 0 -> 576 bytes .../7dfd158e7e1d8c6737ece7d1ea5d67820c671c90 | Bin 0 -> 246 bytes .../7f52cc7f25c0899099277f4057fdac6351907856 | Bin 0 -> 135 bytes .../7ff996c54474adad856bc3db017ddc9959784270 | Bin 0 -> 231 bytes .../81107eec8b4507243f1c673f820a72ea80c18892 | Bin 0 -> 516 bytes .../8134651d726deed781cdf0d3283af116cea8491b | Bin 0 -> 133 bytes .../815c2fb64bab0f77580b953f7c2d7fd0621996fc | Bin 0 -> 125 bytes .../81bbb1193d24b3cf1e462f898f47a2e819e293bb | Bin 0 -> 133 bytes .../820362d206b0835f12b35ff4aa7a813799be8eef | Bin 0 -> 134 bytes .../825915611b3cd3ba1ae6a9c178fe27bbc7dd3688 | Bin 0 -> 307 bytes .../827761890aafb4a26f4da0eb6232a59420c1ecb0 | Bin 0 -> 133 bytes .../82e9c1cb3f406331f68205bcf9a96691dd463009 | Bin 0 -> 135 bytes .../83a952b25c76484e160a04f5f2c0263cc07cc99d | Bin 0 -> 121 bytes .../8526e62eff355f6b808a1f8682ffbbb99efc876c | Bin 0 -> 223 bytes .../85b4691cf62b04e12af3d914153b2f92bda218f5 | Bin 0 -> 685 bytes .../864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9 | Bin 0 -> 90 bytes .../8718dc82bbda78b01bef7fa736f36fdd7db61a2c | Bin 0 -> 382 bytes .../879102898920f7b123cb3bf2d3bce4eab71c38e0 | Bin 0 -> 640 bytes .../87b0269cf7ebd7a44757d8f9a45ef60484904365 | Bin 0 -> 150 bytes .../88053e0d269f3cb40b00c68ef2ee4e51aab1b669 | 1 + .../8930a6e954f28a8c0e4e70c9f41df099a931a088 | Bin 0 -> 384 bytes .../89333d13b767e6b4af04246afb58e77b5e2d7be3 | Bin 0 -> 171 bytes .../8af7ff3e32e33166427356e04d98401ded9a347d | Bin 0 -> 426 bytes .../8b6fd2ab1d0d7fefe124696065e074b2d161c14c | Bin 0 -> 134 bytes .../8f108bc5c869083074bfe9d08f9f9e905e56a206 | Bin 0 -> 375 bytes .../906e954acb728d2e7ed6fb8630672667f09b1f1e | Bin 0 -> 201 bytes .../91583ca2b096602157ea1e68c7d6b2adff9378e4 | Bin 0 -> 137 bytes .../91946201829018208daad41691f4aaa7e2c3eb15 | Bin 0 -> 133 bytes .../92ba02b6268e6c21133447c6518a896157d68afa | Bin 0 -> 221 bytes .../946bfe147670f490b65da4929129a05ba4fe3eb3 | Bin 0 -> 63 bytes .../94a53c59e935429397267a33a6d19fb5bd90c594 | Bin 0 -> 198 bytes .../94af57e79c33b555ed3d577d7d7278776e2e3354 | Bin 0 -> 134 bytes .../94d32ba71497e04e729fed8a7b0eb4bbdd44be23 | Bin 0 -> 495 bytes .../96ca3c3159a62867cd0f67e00cdc29592777fa88 | Bin 0 -> 186 bytes .../97d88e10db105ca8aff02affa4df9105fcf6c0c9 | Bin 0 -> 365 bytes .../97dccd2f5301d606ef218ead83374e2dbf23931f | Bin 0 -> 149 bytes .../987113dad3aecd5a8bc478cc94e11708f3e23b49 | Bin 0 -> 125 bytes .../98ac3859a7ffb3851d4269b8fbc1b408eb36da02 | Bin 0 -> 370 bytes .../98d8745802ae439a6bd8b6cb20b35ba6c942f6ca | Bin 0 -> 63 bytes .../996a0120ca7d868a8a8da7141ed352e18ada4631 | Bin 0 -> 494 bytes .../99925faf1244b710b84a12cb1b602dae69f795cf | Bin 0 -> 274 bytes .../99af875391c1e7c13743893fdd8c3d354e034dac | Bin 0 -> 171 bytes .../9b1bb094b817690bf3f92ed11eaa10371ad3cb0c | Bin 0 -> 283 bytes .../9d23cb41145d5d0643f52b7376b75f5628f95546 | Bin 0 -> 125 bytes .../9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4 | Bin 0 -> 1572 bytes .../9daaa6a59373116fdafd6a88ae78a66f82d3b12c | Bin 0 -> 132 bytes .../9e68ef050c944e5ad80ecb7b4e5023520e190425 | Bin 0 -> 138 bytes .../9f1eabfff336e298505550b3f369c61431289713 | Bin 0 -> 6 bytes .../9f24c5b2bf1b8306de8f5f708476773bfdf8d141 | 1 + .../9f3c56915a0a55918fb711cddc3c72039d2766ed | Bin 0 -> 170 bytes .../a148911d708b9ce5e436a45f9ade17782afc86b7 | Bin 0 -> 231 bytes .../a4d958b6af098740bdd7bdbc670d9d5ff33af0df | Bin 0 -> 134 bytes .../a5481eb2b17062606e626ae7cb9156851f314cfb | Bin 0 -> 133 bytes .../a57da87205e925a5088c9136d5013928ea966bee | Bin 0 -> 176 bytes .../a5bbdddaabff03f981ac4812c9f78744fb59d555 | Bin 0 -> 369 bytes .../a786d0dd572029971ee468ceea31c153df41bd2d | Bin 0 -> 381 bytes .../a7d0b5428d0fee536cad87e3243a8668061164c5 | Bin 0 -> 711 bytes .../a876f0286bdaf5715d37f5446196924288318078 | Bin 0 -> 1240 bytes .../a89172016f91c2d90eae0ec282965f2b980cd43a | Bin 0 -> 365 bytes .../a8bdd4f4f781cc89e87621188db36b8490046042 | Bin 0 -> 365 bytes .../a9d62074bf9e1200cd0a3dea12c106925b58e6e6 | Bin 0 -> 577 bytes .../aa0505ea0b3d4c360a5200a50a010b4a55849fad | Bin 0 -> 410 bytes .../aa3a41b9a808b2028bb83d5279ba42371c8dca4d | Bin 0 -> 1193 bytes .../aabc600f07af79ddb976e2c101f0625f991f2c82 | Bin 0 -> 277 bytes .../aafac2d9b5d50385e892a1c9792bbf9f31530544 | Bin 0 -> 89 bytes .../ab5f3c4a4181cfaec1fbd6949a96cde343cfa908 | Bin 0 -> 604 bytes .../adc6e9d3be69a83a22a8e9579d721139fdef534e | Bin 0 -> 201 bytes .../ae4960ecdce376a9bbd26afbc481619ba303f4e4 | Bin 0 -> 133 bytes .../ae97c55d39f8c51a81fe559e278110d90a8095bf | Bin 0 -> 210 bytes .../aecd29853dcf0d6429665efa95349bca6672d451 | Bin 0 -> 689 bytes .../b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d | Bin 0 -> 153 bytes .../b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238 | Bin 0 -> 50 bytes .../b56d41d9a951ef3ed52a55a640c9741d7d171321 | Bin 0 -> 195 bytes .../b626fd67fd56e710f1ab83f25cd9355de125898c | Bin 0 -> 596 bytes .../b6b36ce62527c806633c581bd83928ca658c5636 | Bin 0 -> 154 bytes .../b73ec5775410255daf79b77df66d8bc3844ac185 | Bin 0 -> 216 bytes .../b82de94562e200e03ce3082d5618fb95d1f61ab6 | Bin 0 -> 269 bytes .../b83ad977325da3e287251f214e5f076700df66c4 | Bin 0 -> 495 bytes .../b8e3f3d19adcbb244d85b968264adf4bc34bbba4 | Bin 0 -> 45 bytes .../b9260c758df1d058735482a8b9b540612b9d2ae3 | Bin 0 -> 768 bytes .../b9924406c46a4a954895fdb416f6ef4f9fbecfca | Bin 0 -> 493 bytes .../ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369 | Bin 0 -> 134 bytes .../baa2017f3f816ea489150c2753fcf2acceed711e | Bin 0 -> 447 bytes .../be34aad9e27b0e5fbeea5acbdefe813dff55c273 | Bin 0 -> 369 bytes .../be998be251e63a0d855a269dec3abd974edf064f | Bin 0 -> 1324 bytes .../beca0cd7b91a6b0af4fc012cf1385952287660af | Bin 0 -> 533 bytes .../bf44fcd5fb4037ca361643ead75091cd7d7591ee | Bin 0 -> 133 bytes .../c09c79dd6953ac6766586c288673bbf07717188f | Bin 0 -> 271 bytes .../c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b | 1 + .../c1a97da39a236c416de37437ac41ab4ff86caee8 | Bin 0 -> 56 bytes .../c24ffe679d844cc26ac590f2657bd36de7876703 | Bin 0 -> 1192 bytes .../c3658e11896a6c7a16d3f40160d91c6e281caece | Bin 0 -> 133 bytes .../c540b77632fe86d68bd3caa3c3ffb92473e38216 | Bin 0 -> 134 bytes .../c5964a09ff096f10007be24c483697813e641050 | Bin 0 -> 271 bytes .../c5be586cbc10f9982b132505e84eed971e375fd3 | Bin 0 -> 51 bytes .../c63c2f2c72fa6788f4e229f4021c3f9001d9ae71 | Bin 0 -> 150 bytes .../c7639de8641dc12f675107b0ce6aee03e1f4ca46 | 1 + .../c7add8dd1a26be2f8429baad24c10726c5e62a75 | Bin 0 -> 276 bytes .../c8f478aa35ec77a762c0289f59baeb61fc4bbb7b | Bin 0 -> 152 bytes .../ca3805fce726847a1fcd57e100bde2c4058afa6e | Bin 0 -> 46 bytes .../cb0a918db754c106d0ba72f50c03eb4b2a434e2b | Bin 0 -> 171 bytes .../cbebcaa181e9397a660ad6e6f48e91c1c92c4c19 | Bin 0 -> 382 bytes .../cc28f7a74f73a3429ef1268030fff5ee64e09acf | Bin 0 -> 119 bytes .../cd54bf63ab01d994be8c966cb92ef919530afc21 | Bin 0 -> 134 bytes .../ce25fe172d2513459fb070d62778e3b7aa865016 | Bin 0 -> 238 bytes .../ce3d342f48dc9d4602f9ec0b63d665fc54a06f62 | Bin 0 -> 380 bytes .../ce8427301dda48d954972a123a2d93a501761643 | Bin 0 -> 476 bytes .../d0b3bfe45b283df4ba481c7e64ec2400dc16ae99 | Bin 0 -> 133 bytes .../d1187b0b6682c51b58021364a766c43108691cc5 | Bin 0 -> 350 bytes .../d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1 | Bin 0 -> 1341 bytes .../d23dd357f27569aa18f9ca99bedc31267977eedb | Bin 0 -> 150 bytes .../d36420fc5040deaf0c097779c63ad45c5dc40a2b | Bin 0 -> 134 bytes .../d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32 | Bin 0 -> 353 bytes .../d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec | Bin 0 -> 232 bytes .../d87db84d6d07adc1eaf599cd5c648b12dd27ac35 | Bin 0 -> 364 bytes .../d91f6aa49d402a9e5af29198f642f5362e768ff0 | Bin 0 -> 472 bytes .../d9438c6b463eb1d6ad4b3927379bab36bbc83a28 | Bin 0 -> 515 bytes .../d95b5a0a0e5f4899ec2810205fa188eaec863375 | Bin 0 -> 153 bytes .../da5cb65f5a4b18e5667b7fa2e9dd0217f738da44 | Bin 0 -> 1368 bytes .../daa4d5092473a26fa51d907baf58b62001574112 | Bin 0 -> 118 bytes .../db0897cfd10616880044b4ecd103a9b342bebdb7 | Bin 0 -> 461 bytes .../db168d324c7afabbd41281dea38fb921b26127a2 | Bin 0 -> 600 bytes .../dcd1e294bde4644814fcce9efae0302f7eb0238a | Bin 0 -> 119 bytes .../ddbc813e2d2bd98f212f672d957c4435ec2d44fd | Bin 0 -> 150 bytes .../de5041627e235f218681ba95d19f2e9173e63151 | Bin 0 -> 233 bytes .../dec155c4b108bd455f1b4ef2aa7c126d99c8d041 | Bin 0 -> 134 bytes .../dedafeddf2d532a8e4c2659d81e774539df6d1e7 | Bin 0 -> 150 bytes .../dfabe7f053a84772adcd20f73f28c4b7d4360091 | Bin 0 -> 433 bytes .../e0c41dfc764c3a0343dbb9bc55109dc45f88798d | Bin 0 -> 517 bytes .../e2e3d56e07f5c7c4a496c232fad04406eefedf54 | Bin 0 -> 370 bytes .../e37e78da0ab0693a777912980c4db4e9a8faa975 | 1 + .../e59134a28131083c665bb210e95ec94903f65b10 | Bin 0 -> 273 bytes .../e5b4fb31f24d7177673bd17da10fcc23bc5fc36d | Bin 0 -> 150 bytes .../e5c82c5fcbe0067ffda8defedc3ce3a7fc1e0ce9 | Bin 0 -> 55 bytes .../e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5 | Bin 0 -> 277 bytes .../e8570727b0bdb9794368ce4e52702cc6fa91660c | Bin 0 -> 232 bytes .../e877fa4f35693b4629b43b5e0a464f9239a8a0ad | Bin 0 -> 381 bytes .../e8c30442040d5df46c96fcf09e200565851fd464 | Bin 0 -> 384 bytes .../e9734e0052649aab1e22f6638d4e4070fd7675dc | Bin 0 -> 228 bytes .../e97a189be7a813919db5a4b277d0978d762e6db7 | Bin 0 -> 596 bytes .../ea1fb604e956587f84c7af5ab9b2d0c39549be41 | Bin 0 -> 133 bytes .../ebc358fc77925b5da9feec9b06a12724f7416477 | Bin 0 -> 334 bytes .../ec8c496dd5407c982d19a0814c282bed0bc8ba94 | Bin 0 -> 2012 bytes .../ec91f82481fda2b90261e991ea8a9bc210ca8424 | Bin 0 -> 216 bytes .../ecb6d9c45861c603a32054d8543fa740598751e7 | Bin 0 -> 197 bytes .../ee988717ae3fbaecc5463e174a397c35afcb400d | Bin 0 -> 233 bytes .../ef7b58b485fa43fe4db625066556e21c53d74c96 | Bin 0 -> 274 bytes .../f02080cd564a6b1a46ceff085f2a44ac015af1b8 | Bin 0 -> 1446 bytes .../f0c2ec4a959d10612cd67742f319075d172da9ed | Bin 0 -> 126 bytes .../f195c020a28dfc5f2fb6af256b524ddcd93756ed | 1 + .../f2672bb54f6a49d0c5b14c4da7ca3f790955c61d | Bin 0 -> 402 bytes .../f2b919fbae73d9d89c6afbd7352a6d6271db076b | Bin 0 -> 134 bytes .../f3494677a550ceb7644ca41d74f5358389eb162d | Bin 0 -> 56 bytes .../f3b6ac34b1e0de8b6a8bc0092af2546f17db985e | Bin 0 -> 592 bytes .../f510a4e3243a5214e171c388d4de68dbb074e34b | Bin 0 -> 134 bytes .../f63885f363b05455c24d547a378d98578529e6bd | Bin 0 -> 601 bytes .../f67021300689c16cff95fac4d33565f788e820bd | Bin 0 -> 380 bytes .../f686aef722cf896abde5defa3dfc6d6533189eb7 | Bin 0 -> 278 bytes .../f69f0bcbf3c1afcd32f0506afca7b37db449634e | Bin 0 -> 247 bytes .../f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e | Bin 0 -> 379 bytes .../f84e4fd02339fdc0d688342523e803b1a786848a | Bin 0 -> 325 bytes .../f99bca591409d3bab5f99232c5af1d7bf871e7ce | Bin 0 -> 245 bytes .../fa21edf3b4aac56ad7c2e224d31b269b099f420d | Bin 0 -> 45 bytes .../fd0faf38df5b04f9a26ecd3084af7e669eb23a5e | Bin 0 -> 249 bytes .../fd3d7ba8e7ced0692c56beb9150b0bbbb546f208 | Bin 0 -> 133 bytes .../fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4 | Bin 0 -> 206 bytes external/boringssl/fuzz/read_pem.cc | 36 + .../01270d57eecae64f59b9b27cc06e3f9eaf2304e2 | 1 + .../0ab8318acaf6e678dd02e2b5c343ed41111b393d | 1 + .../0b08765ad46bb11ac55348755ad5c8e4386bd2f3 | Bin 0 -> 371 bytes .../0bdb9660f74f82a5471210026fdee0b674f1114e | 33 + .../0c4287915a432e6b50e1c2eb0f4ca037b1730aa0 | Bin 0 -> 394 bytes .../0d583f2aee2e15a7dc7eb93af1ecf44203b537f4 | 3 + .../0e3deb2e809b535f39efded20697314a29c8335a | 7 + .../0f29362dfb076a14a103e8bc2c9681fac93c237d | Bin 0 -> 405 bytes .../1078e6b183abbe50aa19cffd741db1cb30e5cf4f | 8 + .../149b4073e8ee2d37455c0d7867c7cffdecf0f8e1 | 17 + .../15dd914fbdc4335ebc69caa9afe37681dd75cc32 | 17 + .../18810634408061267ccb64d68fb85b4ed93515e8 | 45 + .../1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5 | 4 + .../20a000f3932e041a634b759b7cef8138b5b40f67 | Bin 0 -> 470 bytes .../20d3859cd71d9b215f55983a5ac9cce7c0a36cc4 | Bin 0 -> 281 bytes .../217d0e120e43e1899a8ab51009de55038fe52789 | 15 + .../2493849afd1697d00f4c2f36af4522e6a9ba46b8 | Bin 0 -> 512 bytes .../27c891aa76f51487ada28b1fc69ac13c7315c933 | Bin 0 -> 358 bytes .../27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3 | 1 + .../2904f9b6f6cb0ddf9248537b4fb4b2170174b74f | 3 + .../2a7b8759f3267d3ddca22e936df0b21eabb1aeed | Bin 0 -> 471 bytes .../2aaf881c96d0758e5ac244a74deccb7e6363c111 | 14 + .../2ef2666e807e55481eb81bd2bd8369a4422dfc6f | 5 + .../318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0 | 4 + .../358ff4aeb6903affa5d080c317c3270ac4f13121 | 1 + .../35bae979e092abdc6b31f8b3c52ddcafa4722a9a | 11 + .../38fccbaee723a06ca137a952843b58d32d35ef25 | 2 + .../3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181 | 1 + .../3b981c1e4697103278b32ee4e29e3a7b5225d798 | 14 + .../3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2 | Bin 0 -> 325 bytes .../3cdb51f7ffc8ef0bd03265c3a414069815821d18 | Bin 0 -> 418 bytes .../3f46a93da1448c00d2a9f3a62117bd522ce8de64 | Bin 0 -> 463 bytes .../411752e433e18c27f83b9728256082c2ffb77ebb | 15 + .../42650de48dbf62d86a91ede484061f834214915d | 2 + .../488ae502baabc6506f8722dcdc5294940fa5d588 | Bin 0 -> 275 bytes .../4aa25eda7560bbd746d9a69b63965c0de21bb53e | 34 + .../4b32aa9edbd17b2d63390a41cc98739be7d45596 | 7 + .../4d43fa4e63042871afdb387b75a8845d47b46d18 | Bin 0 -> 315 bytes .../548649f5502df5e77b9d332d3f1e29dedd7afdb2 | Bin 0 -> 388 bytes .../55885a3f94688b36e34fac8ce1fd7fcc7bb7208c | Bin 0 -> 377 bytes .../5891dd7c6715eca7f427ed9267de9da72b8e82e8 | 15 + .../58bdb0aea139a2790c2e1a3b25e302892a6c4b55 | Bin 0 -> 439 bytes .../5c720dc0326e4ffa322f706337df9bc87f42fd96 | Bin 0 -> 481 bytes .../667da9df1cde33d635bbde1986827573ed686a7e | 6 + .../66f8b696c46c10a6db20b690e4431b72745f4760 | 7 + .../699044ddfe4887d6081ce2a36c1302814294eb68 | 15 + .../6d1d12ef00c585b4c859479bfa2522f4a447d907 | 5 + .../6d67bafd83bed7aadd641417671e6864dc87073c | 16 + .../6dcb7976d9af4a72b3667926f1fe7642c75685b2 | Bin 0 -> 362 bytes .../6e6aa5ec1653a57a37c043255ab834f6b2228b80 | 2 + .../729be2837328d9f25597b1d605188bc724c632e6 | 6 + .../74a4f38726a49f3a8c06763d58d8fc229b2aa915 | 3 + .../74b9536c60def2f9cb8e83512b80ff8406d12567 | Bin 0 -> 511 bytes .../74b97735df0ee03d5a912734de93772093826bda | 33 + .../7539289d67a0974d16f0ed01ded0a58a02b21126 | 1 + .../78c435e1927ec196afab938edced0b9ee267e70b | Bin 0 -> 403 bytes .../78e4c8a5d73cf074f243ef12a3669fef1e848121 | 10 + .../7a582440bd4712ab88a3e745f928202707585e6f | 33 + .../7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd | Bin 0 -> 446 bytes .../824b6dd27deb9ed157fdc80485f104268f7232fe | Bin 0 -> 507 bytes .../825edbf21bc40ec23225772635ea6390e6d9fb4c | 3 + .../8347c4366b5d668b467fb589c3090f201eacb5db | Bin 0 -> 358 bytes .../874ed5d633d245b10fdda52c49627b43b3f2e25b | 14 + .../88581ebac8ffbea71bb83f704e14d789dbc33f37 | 17 + .../892155ce92d4c3293f48e6fc2097336ba882a0ad | 8 + .../894e092b7fd9f4e0a5911ca106e097d3833d3491 | 3 + .../8c07d6299f33fee89ab0c82e92e06cd558ade60f | 14 + .../8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e | Bin 0 -> 314 bytes .../92207925db84106af0167e887696d936aa41e785 | 5 + .../94514c5c092afe2f8295dc193d506f16c6ea82c1 | Bin 0 -> 369 bytes .../956c8cf1db9220ac8004eb9a75e3ebc1df33a33f | Bin 0 -> 405 bytes .../97c5565f723c0e49787fdec9ed15354760fcb1e6 | Bin 0 -> 234 bytes .../9832fea1fe1c8b575790f59f98404fb61672a3f3 | 5 + .../9940bd2f440a8c1e07dba6476c219349afeae711 | 12 + .../9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5 | Bin 0 -> 315 bytes .../a2bc14d4be3bb4f4deb93ddaa77224db305158af | Bin 0 -> 419 bytes .../a75abe0b4dd03dc232f9192666d6adb369beffca | 5 + .../a92c58dfadb8195fbd90c70b4dc576986dbb7c46 | Bin 0 -> 386 bytes .../aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c | Bin 0 -> 358 bytes .../ad49ff8fb9ff95a8f110b15702f8209df64f8fad | 14 + .../af9207c320f7400ba18dea62fd4af98330ba260b | 3 + .../b034864020154378b78a11122c8f61f81e8009ce | Bin 0 -> 385 bytes .../b178eadb35af688d045ba6bc400396ae0fc7c9b9 | 6 + .../b709f3412c5fb9a0b38a69eee59620a5c3990385 | 8 + .../b92f0f72b6839f6c7ac10f4c663765b89e1fa513 | 2 + .../bc205ed015bb01de66b5a6b5a631d167c8077a5c | Bin 0 -> 424 bytes .../c0348b5dd7aaf73888372a5a6abef82bd0df97b9 | 18 + .../c0596e573f43d2bd5a5d038bf4bd7d073141ddf0 | 16 + .../c45f49452fcdf531f2bcfd100645c535e5b71205 | 1 + .../c504659b0454be5eef0594da6a952f8daf347929 | 1 + .../c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1 | Bin 0 -> 358 bytes .../caf489bb8f6f48e35b95032b2824ca0ffc77d26a | Bin 0 -> 314 bytes .../cc8ceeebb230ca237479e0c3dacafbb5524222e1 | 20 + .../cf1b3d1ed204deed6c62f41d0e706ee47bc802e0 | 7 + .../cfc3b1348ca73b8c02d9aed715d1e0681326888c | 1 + .../d4f0a19ece82b78c82c81eae5b49dc662c6f4a89 | Bin 0 -> 462 bytes .../d959c647c6a5ea641fec147b0de36187a9d2f8c5 | Bin 0 -> 445 bytes .../de2fb44503aca3f82d5466a9489c0735324b214d | Bin 0 -> 358 bytes .../df9fe7d51a89ee267034a2834025f71505d4a421 | 7 + .../e1a6c4096b145ced5362ede6ffedbc49d16ba57e | 4 + .../e207960b1761ba95e7544b9d924459c56e2c4695 | Bin 0 -> 386 bytes .../e3344ef8d734471ef90b16c719cb0f11af2ce743 | 3 + .../e45a6df435a1cecae6547f6dcde626a7e706434c | 8 + .../e7ef91e03a3aa8bd53b2466a2207a5028185678f | Bin 0 -> 430 bytes .../ebcae74985ccc7905a3800c0db2723392cfd2f2c | Bin 0 -> 410 bytes .../ed31baee70d3b705762e808e494b4debf604c5fb | 31 + .../ee06965764fdf6769657e744a61efe7d60d085fb | 1 + .../f123c08d0a46b72fa8989296e82e7aa25ebf16f8 | 7 + .../f18ebc593b87baa03b5e003b7540577001ba6aca | Bin 0 -> 429 bytes .../f1903c6e205ba7b902e53b07e08890ec8179cbd5 | 1 + .../f3f2959361766dbfafbb2f99a4f60c920001386e | 6 + .../f72115838630c70a067e89b98615357fcf19d058 | 45 + .../f9f61f03681250b015a00df3010b89d2d776d8fc | Bin 0 -> 385 bytes .../fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e | 2 + .../fb36b0ce1600b9399d552eab916600c239be5ad5 | Bin 0 -> 481 bytes .../fb64fef6ea2f835804b69ae3d21fb2cac7e4973f | 9 + .../fb6d4702bcb98df173527a5f08d5ac829adb2f9f | 15 + .../fd1cc706033976b86a93d2b0c74b15bb2f31fccf | 18 + .../ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded | Bin 0 -> 511 bytes external/boringssl/fuzz/server.cc | 243 + .../009baa11e6cfa1713bc175dbf069d3bdf0c5b49c | Bin 0 -> 513 bytes .../02601bb35ae3de52d87fc0b48188195b7c07e9ab | Bin 0 -> 233 bytes .../0293d811efcdbb311aa55d23fa9fe9566a64bd2b | Bin 0 -> 206 bytes .../0339d4398642097dd08378d2de67f45825d623b9 | Bin 0 -> 465 bytes .../0353776fd79d387026cfe5366f46f5a7417e58e2 | 1 + .../0356ffe0a247cb950a3c2fc4b125c2ec1d19e480 | Bin 0 -> 676 bytes .../03c9f2cc53c803b0cfa115e252ed40f2546cde27 | Bin 0 -> 208 bytes .../03ed4f1ff81afbad5eedbb5a80b56b23298ec078 | 1 + .../03fc9321fb45199b8fbbdefabc651e84b73f0ff8 | Bin 0 -> 27 bytes .../0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d | Bin 0 -> 247 bytes .../04a3dd601cad12e190ceeddb450e6314c602719c | Bin 0 -> 294 bytes .../05f1de3d83b0d836b0e504f127f6e7445e61400e | Bin 0 -> 211 bytes .../06c1bbafe734f1bce369c330411e508dda42f8fe | Bin 0 -> 27 bytes .../06f786810efbda4369f4d6ae5613eec10c64b2a6 | Bin 0 -> 209 bytes .../0729cde85be33f7f78ed90db14fc05924f755fc0 | Bin 0 -> 480 bytes .../078734f3f4e18e155dd4252624103b2d890f1e44 | Bin 0 -> 877 bytes .../086d77d2f6efbdf4be783a888a44611cf9b14baa | Bin 0 -> 408 bytes .../08bff079591413942c31a9d927f12d39bb9e4efe | Bin 0 -> 374 bytes .../0a331b0b018d33b9eb78982b333415dfc24b578f | Bin 0 -> 835 bytes .../0ad3635fc2fb35c1250f4abddbc4bf40553f87ad | Bin 0 -> 192 bytes .../0b313e12e6182402ed9e6c968cfc82f305db785f | Bin 0 -> 331 bytes .../0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c | Bin 0 -> 1355 bytes .../0c3dce9c0c0498f100445c9bfe487aefa63d16cf | Bin 0 -> 367 bytes .../0cecf043638810fa52a2491cfbcd348613753822 | Bin 0 -> 311 bytes .../0d05d41086700c7ebba2cc83461cfacd83a4c93a | Bin 0 -> 799 bytes .../0ecf26dbd7d24b25a474acc633d53f524ba118a8 | Bin 0 -> 111 bytes .../10aab907c39d9f80fe8e8641e1931ee2ad270e16 | Bin 0 -> 282 bytes .../10e8fb6fd26d9721bb6131d91281755ebf94ef21 | Bin 0 -> 173 bytes .../12a98036ff99402f5be27c4e64456059b440c248 | Bin 0 -> 207 bytes .../136480311a2064a853c568d8d41b0d9c62b3d906 | Bin 0 -> 663 bytes .../1378a7c740e1608a0075be8dc362445b691eaca1 | Bin 0 -> 631 bytes .../13ef34ae06ef674c04808db2c0a8adb1de856546 | Bin 0 -> 334 bytes .../14ce51872fcd9e415b14936b6692472f445f4489 | Bin 0 -> 589 bytes .../1584b2eb5bc2f0e9351f5630ba9f513ffe9c1089 | Bin 0 -> 1553 bytes .../1628ba4f9bbb8c96aecc47305f93e028040bbdac | Bin 0 -> 235 bytes .../167171e86e3539873f2f6d19146c797774a6bcb4 | Bin 0 -> 368 bytes .../169029c8da9497dd15c0f8ae2f2ce585568e0659 | Bin 0 -> 2699 bytes .../1754c50fb526624f67c4c286a29b47da5caea506 | Bin 0 -> 265 bytes .../1776797c43f6caab7f17dcd0ba1ea74e7a94b39c | Bin 0 -> 212 bytes .../19a2a537172038059839e797eaf487cc317e9ffd | Bin 0 -> 192 bytes .../1b163f7dc072468d689581829dcb93b9560e4e97 | Bin 0 -> 588 bytes .../1d9b4cbce0998360304d17a5273b57d1bb6fb33c | Bin 0 -> 491 bytes .../1de612cf9b75c023cf183e85997a0797657266a3 | Bin 0 -> 2036 bytes .../1de66d7e26f3df137ad2868570263e7fa14c0aff | Bin 0 -> 238 bytes .../201a57ee9fff7cb160f28aea6084c520d59d5537 | Bin 0 -> 169 bytes .../205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4 | Bin 0 -> 234 bytes .../20d3cfe62b986e9fc74c2bd4f8d793928df88f4d | Bin 0 -> 374 bytes .../217f128931d1db8e7a12784e793d3613f7a584b1 | Bin 0 -> 307 bytes .../22eda57a5819d876bbe9e0d938d4ceec5ef7bde0 | Bin 0 -> 214 bytes .../238118230b83a2beac4fc04e8ace080c96427e29 | Bin 0 -> 979 bytes .../260ef2d666d03e5451109135b50cbd9657fc6964 | Bin 0 -> 614 bytes .../2694758ce91a4233066ec157880fec851c16c59b | Bin 0 -> 1157 bytes .../26962d40bfb0f49cdded97cc981d789e4699b08c | Bin 0 -> 738 bytes .../27e55ccf7c64899aeb1011629cd1edc492730dff | Bin 0 -> 107 bytes .../280376c0907c566a201a131ab01e567aca85513a | Bin 0 -> 250 bytes .../286456dce363ae8bf19ce6ebbf027889cdd351f3 | Bin 0 -> 27 bytes .../28bd4185ae535c2d6bc9d848db4b4039e60dcfa7 | Bin 0 -> 141 bytes .../29000511dd6707b7e8c7f10ed70340e1391dd3c3 | Bin 0 -> 822 bytes .../298752b8d5f8cae623a95764289da5f0d94afb24 | Bin 0 -> 310 bytes .../298ee587ceb3e7685ab165fee56780031113c766 | Bin 0 -> 179 bytes .../2badd38a1ebbaccd61bfdc3d79e1f79f585ed390 | Bin 0 -> 863 bytes .../2c79975ee52b16aa14b8faaaf43eccfac72f4651 | Bin 0 -> 236 bytes .../2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17 | Bin 0 -> 141 bytes .../2de59b00466c89d774e8dbf353761c4611d65e2a | Bin 0 -> 365 bytes .../2e830d13eff02a0da6b6ae20ca271cb8cdbdb64a | Bin 0 -> 191 bytes .../30215b01f68c655988e2be5d071767adb918ab41 | Bin 0 -> 266 bytes .../302f9b349fc7d906fd38893a85431925e319508e | Bin 0 -> 366 bytes .../317bc318af6286bf0ac2d679d3518b12b75c49e7 | Bin 0 -> 513 bytes .../31f6f995d8cbf4291e5197d421e78de61bcf53dc | Bin 0 -> 348 bytes .../31fce22e8c242afcd1c122dd1623c77e0b1b4a0d | Bin 0 -> 191 bytes .../32302b428fdb884e4de50171bf7897354ee35ee3 | Bin 0 -> 499 bytes .../324bf110726da4cf6de7bb28a0b2a99dac045768 | Bin 0 -> 238 bytes .../32cf502f739bb71624940b06ce964422a175b6da | Bin 0 -> 838 bytes .../32d38a0276c734a25c88823b79710dafce4721f9 | Bin 0 -> 375 bytes .../337d50236ca01f8e660527e1c7f1190188cc5af9 | Bin 0 -> 167 bytes .../34b4eb249c57036a82496931b7823a8abffbfe43 | Bin 0 -> 309 bytes .../34f2704805423aee640b1ad1fefb54ff5c49bf7c | Bin 0 -> 429 bytes .../3593bd1cfd62ca2f53432dd7444b452e1d7c7206 | Bin 0 -> 538 bytes .../35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3 | Bin 0 -> 1985 bytes .../360b997587a9c6f4773e1ccc2f56a3e60d7d6b1c | Bin 0 -> 8 bytes .../364ff4d7992806bf179b156ab465400e46fa515d | Bin 0 -> 141 bytes .../3697165cd5d8c192e32be9f6f62fb514910fd1e3 | Bin 0 -> 500 bytes .../37826e5324f024632f3fe4d6aeb6c5e0cd33b770 | Bin 0 -> 308 bytes .../3791653050209ed3d11f6749e0d8e874fdc68b89 | Bin 0 -> 1545 bytes .../37a863dd9c47ee54937c65c6e43ee95667808661 | Bin 0 -> 480 bytes .../38fb26179fe6db37a43708ebc02df87cfe01fd14 | Bin 0 -> 502 bytes .../3928f49b93a191a465e788af538a969278c14823 | Bin 0 -> 1245 bytes .../397b7e5b1afb2f886fa46fe47e3340e9e25db74b | Bin 0 -> 137 bytes .../399976c7723f20941ac86dfbc66090453e496528 | Bin 0 -> 434 bytes .../39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e | Bin 0 -> 374 bytes .../3aaf48199b093ba93f0e1ddf972782cc99e613d2 | Bin 0 -> 210 bytes .../3aec20067842293ca181d1c98b1caad6b10153c1 | Bin 0 -> 427 bytes .../3c4f860903933d2305eb9ce4eaf53144d79c5843 | Bin 0 -> 371 bytes .../3cbf37bfdfe9dd100367e512ba6298dfba7bf294 | Bin 0 -> 243 bytes .../3d1a07692bc1687bfe9d4ee6f54811578fc54884 | Bin 0 -> 141 bytes .../3e71382d2831304e50054a0175baf664fae49608 | Bin 0 -> 191 bytes .../3f66254e9c33487a194952aef2b4b38cae181ff7 | Bin 0 -> 377 bytes .../40ce675771c2d778f8c746a5d0adc41d6236ecf9 | Bin 0 -> 622 bytes .../4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9 | Bin 0 -> 28 bytes .../41aa254eb9cf327e23976ad968de5f6c6fd41929 | Bin 0 -> 238 bytes .../41b3e56ab8d7752ea12fb170efdc8318f822a384 | Bin 0 -> 238 bytes .../41fddbda3d28306beb8045d74be6c048c8d95a44 | Bin 0 -> 321 bytes .../435e84066c2a010e52c2452852816bf2ac8ab348 | Bin 0 -> 528 bytes .../448cdd2ee6d4f30585785ee406d7a5be76783814 | Bin 0 -> 211 bytes .../45331d2e2c0f21e6f070d26e381bd0fa0c82ab81 | Bin 0 -> 1354 bytes .../458469682e541e27218f68140b3ec5e08a160907 | Bin 0 -> 233 bytes .../45c8ed787ce862a29bbef404b84fd672d4e44c02 | Bin 0 -> 25 bytes .../463538114921dd033e2b968874a8d0103d8a0550 | Bin 0 -> 3535 bytes .../463b9a9c1edafa2d42b1b0dbd9390186002eb775 | Bin 0 -> 179 bytes .../480fdad19f48ccb66c79e4daad4bf4c189334d76 | Bin 0 -> 193 bytes .../492a81af49a5a0f6e88192f8d8a6212bb15671f6 | Bin 0 -> 368 bytes .../499f80ae1a49f344f6ea00678211e0bc08339451 | Bin 0 -> 168 bytes .../49c09c1aa90fb1879802f348f2564c7a67f07f61 | Bin 0 -> 608 bytes .../49d88822047d201e1ffc6759e61a917886c899c5 | Bin 0 -> 238 bytes .../4a33f80e3245dbac94867a309485514038284345 | Bin 0 -> 2320 bytes .../4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1 | Bin 0 -> 644 bytes .../4b8a432fa4bf47f45d9c2ed257f0a958fcc94f9c | Bin 0 -> 177 bytes .../4c19babb1cd203839c0849f977058b7eaddf39be | Bin 0 -> 352 bytes .../4c948e8277af54d8f79adf1fc5f748f51f2f99dd | Bin 0 -> 191 bytes .../50a4c64c532174353794ca054ad60e30ef25110d | Bin 0 -> 267 bytes .../50bb213c61033f9305b0bd3828c72505ec6a1caa | Bin 0 -> 141 bytes .../50edce6beb7be88fd0fec26d84bc2706432adccd | Bin 0 -> 601 bytes .../522d6829d952b1611ed141de5d2b500e95f46133 | Bin 0 -> 232 bytes .../52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72 | Bin 0 -> 169 bytes .../52bd453551c468e4fa1503fb4b113d6b143dc553 | Bin 0 -> 352 bytes .../530aeb352e1f3e82138f4a3325463ab8738ee045 | Bin 0 -> 141 bytes .../545801d21d7321adfc5e2fec30ad21125c612bbf | Bin 0 -> 3980 bytes .../557f33e444c12f4ae11cbed2463509e2b76c4838 | Bin 0 -> 167 bytes .../5686ea1bd2b626e81ca079482a81c4133a589e0d | Bin 0 -> 192 bytes .../57779cd03374bd1ffb254ee0749d437108879a28 | Bin 0 -> 1426 bytes .../57bed14657b0ba761b67f5663af6dbcf891e06cd | Bin 0 -> 374 bytes .../58080a322d37e7d8cb9fa7585be92689a971ffd6 | Bin 0 -> 155 bytes .../59849e9352267bb6c79fe78960a8369797da6281 | Bin 0 -> 379 bytes .../5a09520c67133379b720d9b4aa549e6a4f76b604 | Bin 0 -> 207 bytes .../5b492ed27785260ed00654e71e9b272071618fc8 | Bin 0 -> 25 bytes .../5b598ddf2bc6d1b376c733a935306e45cb247879 | Bin 0 -> 234 bytes .../5bef1a165880066972ce67fc28c01f46bc306e6b | 1 + .../5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a | Bin 0 -> 217 bytes .../5edf5a17f9862feb006b9400cafed2843ff80adf | Bin 0 -> 169 bytes .../5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0 | Bin 0 -> 551 bytes .../5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8 | Bin 0 -> 142 bytes .../5f70e0ee2f616a7b4bbb743a9b1b91517bc3f057 | Bin 0 -> 1848 bytes .../6040b1427656967d16ff771db3d32ecc5ec579f9 | Bin 0 -> 35 bytes .../60b3caaf413cf16a1bbb4741cdbbe66259540902 | Bin 0 -> 335 bytes .../610e3905ae7cbfb26c383c894489c45fddcc644e | Bin 0 -> 250 bytes .../61d0f602fbb64038787d3c79591a4673f84d591f | Bin 0 -> 608 bytes .../6288b112228f24ecbe24c87d06698e244e15a7ee | Bin 0 -> 454 bytes .../630800205061e44da8f2a98f73192b6c02ac2cda | Bin 0 -> 88 bytes .../63103eb0da3c238ad20edd649bc2e0ff1d65d485 | Bin 0 -> 356 bytes .../63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea | Bin 0 -> 167 bytes .../6427c33410538cfa3263291caefc5fef483baee3 | Bin 0 -> 294 bytes .../64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7 | Bin 0 -> 512 bytes .../65ee094875fb0e661e0a83872c5ef2a2b96456d3 | Bin 0 -> 240 bytes .../663aac853a26b5b7d366b1084fa0b89e8c1042c7 | Bin 0 -> 517 bytes .../6804200e6128651336b64a491deff4c045edea10 | Bin 0 -> 435 bytes .../68ed9e990a43456def6c94ea616668f5d17d739f | Bin 0 -> 221 bytes .../6a28ed0197ddb6f8ceb4ca87ab463fa80152db78 | Bin 0 -> 387 bytes .../6ad9e29108e9b826b4ae5ef1b6748dcaee3647bb | Bin 0 -> 175 bytes .../6adff19a28e5d20cbf9cb4cc576b86718d7b02ce | Bin 0 -> 27 bytes .../6afb292e0d86866ead887381e4bb95c6abbd00a7 | Bin 0 -> 224 bytes .../6ce759d9375ef41abf26be9e5f79447f9cd10753 | Bin 0 -> 307 bytes .../6d77b6fa38172e6716a8faa9672364199025be5c | Bin 0 -> 328 bytes .../6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06 | Bin 0 -> 183 bytes .../6de87dc2626b2b0068ba2d981665d6b366c3532c | Bin 0 -> 206 bytes .../6eb8ee617c043084a08fd19105f897bf9a5ce7f0 | Bin 0 -> 355 bytes .../6ede1a48fb0da7644f9bc8f91c9b8d717710a359 | Bin 0 -> 310 bytes .../6f65f68defc58c4e70ac774728d73df16b035890 | Bin 0 -> 238 bytes .../6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a | Bin 0 -> 390 bytes .../7033506106b6f14d4b73713d409503581d6d83be | Bin 0 -> 232 bytes .../703da7bc1a86d25c4a719ffd8dd758eb593d151c | Bin 0 -> 182 bytes .../706f54bf24538976566b61e852b1c4d9ae1119f4 | Bin 0 -> 176 bytes .../7073f6010cff349f012670f14da7428b53755634 | Bin 0 -> 24 bytes .../70c37f8fac66c1b1246354d4c7236ee2dc283e5c | Bin 0 -> 185 bytes .../743fd36937f52741a4cc0a8657203cfd02c46aad | Bin 0 -> 822 bytes .../75cc89a6fd3156770999a138f3d2a050344364ad | Bin 0 -> 826 bytes .../75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af | Bin 0 -> 230 bytes .../77b55b3457cd7ea618c65886edf5661322f94232 | Bin 0 -> 148 bytes .../7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58 | Bin 0 -> 275 bytes .../7ad83ae355cd42307de44effef5fa238db8de93e | Bin 0 -> 250 bytes .../7c13a00efcf05848cca0015ec99705939bd7762d | Bin 0 -> 1296 bytes .../7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2 | Bin 0 -> 306 bytes .../7c7edef35a80358b098ede960f7a254c2920b945 | Bin 0 -> 168 bytes .../7c8d8a6475c235eee93a9132e3efcc2d8cf2457f | Bin 0 -> 2049 bytes .../7cd231570a9a7ba088cc00447c836839564bdc71 | Bin 0 -> 1565 bytes .../7d70d47487b1c99d7a154307e976905551bff147 | Bin 0 -> 31 bytes .../7d7bf92eb0b77728910683eb97d356df3bcafd01 | Bin 0 -> 196 bytes .../7e1dd1d1d2f30337a345ee16662089530e19ba10 | Bin 0 -> 321 bytes .../7eb254ed656a33e05bdc3def3565b7ef45d30cee | Bin 0 -> 875 bytes .../7ecae41dba4999017c7282a2e17c5be94d13bb35 | Bin 0 -> 497 bytes .../7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02 | Bin 0 -> 419 bytes .../7f762ef581bf5b21dc2b9e5d0a6f01556d02827d | 1 + .../7fd784bcc4b1e7cca034bd5e90d013cdd5ed37fc | Bin 0 -> 119 bytes .../7ff26dd574e66a7f3425f1aa68717beb16a6943a | Bin 0 -> 2413 bytes .../7ff47a645111533c4c4a5680485aebec1fc71ba2 | Bin 0 -> 350 bytes .../805673ac41123503f5ec4d5a5b26d0c49751d219 | Bin 0 -> 168 bytes .../807e902da37bf045992967c88bdd7ef5e3311079 | Bin 0 -> 308 bytes .../81002fc62e533b6df9bac981650d9379efa1538e | Bin 0 -> 198 bytes .../8130aa1cfff870363a58b1aed00aeddbd08e3439 | Bin 0 -> 478 bytes .../815efc8337a4dafb7acac5e27f188729e794ec1a | Bin 0 -> 388 bytes .../81908c24376fd3bb3e3678298583972f3bc21629 | Bin 0 -> 215 bytes .../81a73f364c5a7966e7fc06aa0208e16836324ff9 | Bin 0 -> 572 bytes .../81aed319be7488358f8fbf252561c12c68f88a96 | Bin 0 -> 30 bytes .../832fd1d40a6a34cb526a2a0d51d7f98c01216e27 | Bin 0 -> 374 bytes .../83a1fe57841a03e9f62e5c4c98121779d027d7f4 | Bin 0 -> 141 bytes .../83a7146b87bdb59b9d181983c0b15934fa141095 | Bin 0 -> 224 bytes .../84128b248dde02f39d9038b0d9a92be858064b93 | Bin 0 -> 192 bytes .../846f489beaa418c54a7558e3dda22fa18a613344 | Bin 0 -> 183 bytes .../84cd4487cc10e218fac4e005a2f36e6cda07f2f1 | Bin 0 -> 218 bytes .../8538cd3259ad3d8f06f9ae921b6a365b33548097 | Bin 0 -> 2595 bytes .../8550e0986e06c2c732bf5707cf1679d18d4018a7 | Bin 0 -> 1517 bytes .../865424250f3372fd80022ecbd3030371eb7484bb | Bin 0 -> 167 bytes .../87312b033ed008fdeb949278f51403dd15ca3f77 | Bin 0 -> 306 bytes .../87bb4f11ea55340864b41f92cfd96699e34dcb01 | Bin 0 -> 676 bytes .../87d63b2cf65c4a56d5c6c7354e122472c1c86985 | Bin 0 -> 178 bytes .../8ae391773c823fc455913bb5ec33047dd840e9f9 | Bin 0 -> 297 bytes .../8b4aeaa1d3ce97c435b07445e55b778db0f8fda6 | Bin 0 -> 238 bytes .../8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c | Bin 0 -> 182 bytes .../8bb068ede7bfaba9627d9820634c0eb4289db338 | Bin 0 -> 107 bytes .../8d8899a4a0aca676e6e4df78003f237073f850e4 | Bin 0 -> 335 bytes .../8dc9927297dc363f7858864279aba3d2e7f1abea | Bin 0 -> 231 bytes .../909f5acb8de0079ff4c8b107d272574085c8f779 | Bin 0 -> 215 bytes .../90d7f98a4df715ea087a5ac5f96c20d968cdfa11 | Bin 0 -> 26 bytes .../92d1725e6cd758eeb1139f214d4431b8c8cc8006 | Bin 0 -> 238 bytes .../93fd04136be09b9ff4986bb17fee653ba10c3f86 | Bin 0 -> 309 bytes .../94581aeb5d99c7ec11279264a94e4d3fa845c41d | Bin 0 -> 298 bytes .../968d9f7d5bf7e11e205dedf844a771f185c777a0 | 1 + .../96e88c6539e937f868152998ba46a8decab25bf6 | Bin 0 -> 169 bytes .../971714820d6742e5e6d84e95a26c1e526898c726 | Bin 0 -> 63 bytes .../97835515e9845c8094b017636f42e40db853e358 | Bin 0 -> 515 bytes .../9841a3665b7d75fd247655a673018735e69e13ca | Bin 0 -> 333 bytes .../98c12c0d2c35bc2141a8c5fd2438bc6e237df335 | Bin 0 -> 182 bytes .../990b7bec61d2e85dc617b456db532b738791dfcb | Bin 0 -> 11 bytes .../999678f54ffad44b964188ff7b839fe323e5d8a0 | Bin 0 -> 465 bytes .../99f84ab3877198979a5644873f3078e56d9bce74 | Bin 0 -> 364 bytes .../9a0a22651c45daadb5e28c2fb5a722050242e3ad | Bin 0 -> 325 bytes .../9d6670b22713ef933f7023a1de30f1bf0f153b7c | Bin 0 -> 13 bytes .../9f47049690a48658cf855cada2ba67ca467f6b4c | Bin 0 -> 231 bytes .../a17c22b54007188166fa0ddc4afc05dce426bd06 | Bin 0 -> 222 bytes .../a2119075a436f488b9caddcd0d2e78f08eb9a5ff | Bin 0 -> 192 bytes .../a38a19f50fd1cda8c1fecbe27ac83324ca211b84 | Bin 0 -> 216 bytes .../a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b | Bin 0 -> 496 bytes .../a499e6063ea86dada60bc06951f13039e9c1f3ac | Bin 0 -> 604 bytes .../a501e54923687ec3b05c49c06457d145342f47f5 | Bin 0 -> 223 bytes .../a522a19032823024bb19fd0df2d4f26ea54a896d | Bin 0 -> 25 bytes .../a6d011ffcc98cf16234a7d20ccd4db30809b39ac | Bin 0 -> 852 bytes .../a7b732b28fef3a7d2797d793c1d972f3460e50c9 | Bin 0 -> 210 bytes .../a805ac78ea5ac34b9f16d1db6a2586bebb804d1a | Bin 0 -> 180 bytes .../a8461484408a8b22ac775b72a0fae9362e1bbf46 | 1 + .../a851fcf09f23a5980550492a7b6a9af5e55c786b | Bin 0 -> 368 bytes .../a94773a424fb3dd39e61ef294cce3a226002085f | Bin 0 -> 250 bytes .../a9aaf8b0c4396ca9a8905c257cadad38b015f715 | Bin 0 -> 414 bytes .../abbc509bc116d4cb303b4efc226110e3d2b1f9cb | Bin 0 -> 355 bytes .../ad657af7ec670f63bf7b699bfc2d7784d9679c75 | Bin 0 -> 309 bytes .../adbf34bf3b6c339e3aedeb5bda369026f1041498 | Bin 0 -> 510 bytes .../ae1addcfe82e6e924c3d5186aebc7f4595a34f79 | Bin 0 -> 625 bytes .../afb52e07276941f1176601b4855bf5d96773221b | Bin 0 -> 450 bytes .../b0d31fd682c73610a7879d9f4932388b95d0bc27 | Bin 0 -> 603 bytes .../b110009f633e2daf74b775a2f29521e49cb50021 | Bin 0 -> 215 bytes .../b161a1165fdcc35082d791714fa697f88f673f32 | Bin 0 -> 179 bytes .../b19d4db2ac81eca8ec7270e840ade3c0d0f9c961 | Bin 0 -> 272 bytes .../b34fe229d5704686c2f583c49081e780f9eee0f0 | Bin 0 -> 167 bytes .../b3c32ca3d0de7706ec31c174e56d3f3a02a29e74 | Bin 0 -> 388 bytes .../b5a0df0a67120a113aaa8e66d2a89e92eb83518c | Bin 0 -> 169 bytes .../b5e350594b8a451635004e4adbac220855746f95 | Bin 0 -> 35 bytes .../b635afc6b7eb4837e06e295a0b7be1dd4304c938 | Bin 0 -> 182 bytes .../b68c52bcc48b4828c3b9c0a1e549333b33fc3571 | Bin 0 -> 702 bytes .../b6a51620f85e0bf69b534402b0d0397ceb834e9b | Bin 0 -> 205 bytes .../b6b9e9149d9da8a20823ddd794b17f3e07c5902f | Bin 0 -> 298 bytes .../b6cc929d3a3e0c526463b451e5a9e3b00d105368 | Bin 0 -> 847 bytes .../b6e477f0159ebe9a37e048602f357a148ddb3b32 | Bin 0 -> 231 bytes .../b7801a9236dd2281a0acc933019224d6c1dbf257 | Bin 0 -> 809 bytes .../b7dcbba77174c4a08c659a593ec3f5ebe5094343 | Bin 0 -> 51 bytes .../b832a18069022b70323d9a0ccdf38a6bd3d9aa5e | Bin 0 -> 269 bytes .../b8a03d1b641ed88f0951d04943b8a07050370f7e | Bin 0 -> 238 bytes .../b8dbc8daf864513bd67dfd27651067ec8cee20bf | Bin 0 -> 374 bytes .../b9331377e2a9f03a15649ff1ed311d9c70057b9c | Bin 0 -> 234 bytes .../bb589d0621e5472f470fa3425a234c74b1e202e8 | 1 + .../bcbe93c3346d8dc6de9b6db6963d7787440498a8 | Bin 0 -> 642 bytes .../bd2f13c2ea9251c8f5984e4801964d2c535e979a | 1 + .../bd6b8551ceeb4f504ef7428a1fe188ad343c9e70 | Bin 0 -> 519 bytes .../be6b4b2ec34f17afc2630bd13ceda59817a86bf0 | Bin 0 -> 167 bytes .../bf85c5738caa0751b6192e3f2210153e16190e7f | Bin 0 -> 143 bytes .../c095ac0fc0793343959fb8ce7b9f0a448a679a72 | Bin 0 -> 339 bytes .../c0b121e41d0a429854a5967bd6d1367414333246 | Bin 0 -> 567 bytes .../c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0 | Bin 0 -> 1158 bytes .../c1774d0621d44733a05eb58edf38f7f994ada191 | Bin 0 -> 168 bytes .../c2316b3de8f79e6021ba25dc3522c440cce56abb | Bin 0 -> 254 bytes .../c25117880ac0e46d72797ac80e67ea5c8d8d0e8d | Bin 0 -> 167 bytes .../c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8 | Bin 0 -> 182 bytes .../c39ffbdda14f7196ff35c67a2589bcd873e07e84 | Bin 0 -> 255 bytes .../c3b18d830d2afda016d1c6d2cf8656707936d9aa | 1 + .../c4530fd98a3f55c874638e7703b4755dcbf03d25 | Bin 0 -> 181 bytes .../c488daaa980c5b4637c14a7a9dba41f905ad40ee | Bin 0 -> 182 bytes .../c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 | 1 + .../c4e90f27e3780d2596c565dbc6b23e8a62a32671 | Bin 0 -> 224 bytes .../c5d128e9ef95c5ea1941b1583bf5d67433efa122 | Bin 0 -> 236 bytes .../c6f9e5c4cc9a6f8af4df7e633ba7267244810910 | Bin 0 -> 141 bytes .../c783f8c9cfb382374aa8359a3ecdd689140aa3ac | Bin 0 -> 280 bytes .../c7ca9b384fb874d12f54ba800b7db3fc35d47d1a | Bin 0 -> 26 bytes .../c83f7080ddbe04198dd715887ca44666a1fb29b7 | Bin 0 -> 195 bytes .../c877371f7bb5a27b25fd354f7643c95481f7c970 | Bin 0 -> 141 bytes .../c92efc4a4757c37f8373d5da954b114eb780dc52 | Bin 0 -> 225 bytes .../cab79dd0612ba0a5213ad42c88619860f9e9485b | Bin 0 -> 502 bytes .../cb0bbbd9c59f0dc9dd030885b65afb8524a4fd45 | Bin 0 -> 653 bytes .../cb3f92a2f51c86bd52c598116e73e393d003590d | Bin 0 -> 167 bytes .../cc060d9eb0217741ce6e78b428aad5e49f26d6a2 | Bin 0 -> 141 bytes .../cc646165768ece9d7b3a53295139c652758719eb | Bin 0 -> 192 bytes .../ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800 | Bin 0 -> 245 bytes .../ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc | Bin 0 -> 374 bytes .../cea030f4e5beef22bd9892408a0708bdaf3c3743 | Bin 0 -> 167 bytes .../cef9da3480218f4a353a1d4b10d5095b2273be49 | Bin 0 -> 8 bytes .../cf4553b998285a8ef7bcfbb845288955302344b0 | Bin 0 -> 168 bytes .../cfeda2740e1750c2a71175a21457eb3359d36e75 | Bin 0 -> 190 bytes .../cff5833dd4809d38118c760600d7a4a06fb63912 | Bin 0 -> 749 bytes .../d044e375a03f40f24ca4fa054419d5425912d8f9 | Bin 0 -> 141 bytes .../d0846c7f54810ba3483ecaaa84e73b5c87fb72fb | Bin 0 -> 233 bytes .../d0d6d66d04f08f11ad9fb417b8482b62a1c488ce | Bin 0 -> 424 bytes .../d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6 | Bin 0 -> 920 bytes .../d1730107611b33be2922586c05825454c3bb9cc9 | Bin 0 -> 263 bytes .../d19c0da91a0bb15ee5b7b480ab2304557ba9c079 | Bin 0 -> 368 bytes .../d2c6c9be5638d2a45f14c15f4f73c14f3ef59799 | Bin 0 -> 194 bytes .../d2ea7356790b71e17270aa885b1440228810767e | Bin 0 -> 424 bytes .../d34d64db9a73ba104b383f991f4ed92a60987cf5 | Bin 0 -> 295 bytes .../d374b7d09d4196c596a2586a88256fcb1e9fcb2e | Bin 0 -> 391 bytes .../d37f0db1910aa2e906b546fc035f2831addcde43 | Bin 0 -> 457 bytes .../d3a86e7b61070b78611766d587f5c1bae1786b32 | Bin 0 -> 183 bytes .../d3cf42aee90dedb4148eba308eaa0087219d8773 | Bin 0 -> 244 bytes .../d47d2dc334230da3acf3f34b782e2fbb79dcce72 | Bin 0 -> 429 bytes .../d4f46b0706389e9680ae047f98bdf38bc31eabd2 | Bin 0 -> 180 bytes .../d503f0f105b563087338bf3517a269ba8b130f1c | Bin 0 -> 185 bytes .../d6a617adce65f5e26d0b216b04cf5faf774ae5df | Bin 0 -> 288 bytes .../d7247e3132134e04b695907afdce71681fe30f60 | Bin 0 -> 200 bytes .../d741dcf9b121e34a0141845b9329ea92f15ff447 | Bin 0 -> 355 bytes .../d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27 | Bin 0 -> 284 bytes .../d8425676bd4a9091fee7680cc80ec7003a8230c8 | Bin 0 -> 35 bytes .../d8f891994e13e538a9ad177d687423c92cc9a6c1 | Bin 0 -> 195 bytes .../d94aefab9d08d20cd1703e87f92501579ddb9fe0 | Bin 0 -> 226 bytes .../d95337213aefb62a5cac46bca1b4bc2c61538677 | Bin 0 -> 224 bytes .../d9d4ac3b729317fced3cd857d1c6b1896b798434 | Bin 0 -> 461 bytes .../daf8423d0e1956a5daa501ed104e5b6d08cf4e9a | Bin 0 -> 630 bytes .../db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e | Bin 0 -> 364 bytes .../dcd0ac87b1cae69418b6f6f95154186f6f039dd5 | Bin 0 -> 352 bytes .../dcf711a0bfa12e4616d3b644d381cb75d3113a5f | Bin 0 -> 286 bytes .../ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155 | Bin 0 -> 266 bytes .../df0c69339b2d0625f2114cc0665bf85726fd7737 | Bin 0 -> 376 bytes .../df38c584e0a47097ffb84eeeb233378bbe4adb27 | Bin 0 -> 1948 bytes .../dfc889e877441114c78c93a2c27862d90b8ceb0e | Bin 0 -> 325 bytes .../e0c910a95189f32b6f53ae4738352abd5a02bae1 | Bin 0 -> 253 bytes .../e2c8667b857090a2a76111235b1dda0410d0531b | Bin 0 -> 183 bytes .../e4cd6455558a3a56b6cc322044eb2e76bb204c11 | Bin 0 -> 200 bytes .../e4f601c4530865ed5c238194692199b65cf6846e | Bin 0 -> 819 bytes .../e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60 | Bin 0 -> 182 bytes .../e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf | Bin 0 -> 383 bytes .../e76d51463070189be289c46db1fef08f8c44ce3c | Bin 0 -> 374 bytes .../e7ef72fdab634ae7658cd862feaf944d0ea3ce2b | Bin 0 -> 182 bytes .../e82273fd2b509ffeaa0a06138fd48878b708c557 | Bin 0 -> 305 bytes .../e82e55fa1dc031602bd9db99ef3bfba52828a7e7 | Bin 0 -> 167 bytes .../e94b2714af564e9e3ee8b464514a55c2ed46d8ba | Bin 0 -> 46 bytes .../ebe605930e73da69d25b156cff9dbd13f0861484 | 1 + .../ebe60c3b30c6c5bd1ce23e3a033ddfeb4515b303 | Bin 0 -> 38 bytes .../ec1a7fa84fb643ff5d8c52e225edfd1605218874 | Bin 0 -> 358 bytes .../ec744f66e6351373f00a36829029d73d597cb976 | Bin 0 -> 366 bytes .../edd61df88481ddefc20a02e326ada5a6eaa41dec | Bin 0 -> 343 bytes .../eeb0f79e9507ef27c237ddaac2fc859a1fee8bc9 | Bin 0 -> 26 bytes .../eee65b9d72dd80d44e3d9f7fb7115503131bdad4 | Bin 0 -> 107 bytes .../eef1516de918dcc086d39edc23206bcc7715679d | Bin 0 -> 223 bytes .../f00bdfcb2a5a22ef03bbdcc3e661335eb4d11c84 | Bin 0 -> 255 bytes .../f06014fa4a9681f2e1e977e4bca8d86a575a8c18 | Bin 0 -> 282 bytes .../f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30 | Bin 0 -> 356 bytes .../f1d972ed5d10bcd4741c0f5eeee723ad245a6a86 | Bin 0 -> 230 bytes .../f1ee7dd7ebf5b68a385e5dc1f289116c67aa5fd5 | Bin 0 -> 479 bytes .../f219ee1ce52714fbdbd6e33c012ec4082efc691b | Bin 0 -> 274 bytes .../f34cbb130fef3f89599402ea6d721b7eb3e5615d | Bin 0 -> 176 bytes .../f38adbdf7df8def4641eeb1a28ce0ecf8d9b2fe1 | Bin 0 -> 191 bytes .../f3c3c4eb731e6cfafa5b13667bf2928646d8134a | Bin 0 -> 500 bytes .../f4425d6adf697df0f85be8758c0cd21d6a5df57a | Bin 0 -> 56 bytes .../f465f74ff5a9e4248a332bf306f45cecd8314322 | Bin 0 -> 393 bytes .../f7bf8c5ec7a71cf8a7f713279901817705eb6ab9 | Bin 0 -> 411 bytes .../f80cb481d2d6d253dd4fe0140055a69699ae8fe6 | Bin 0 -> 335 bytes .../f8c000e8f3090950de2c5c1844a45c9148fb9a0b | Bin 0 -> 1889 bytes .../f93d7c03d0cdf7ca4313c80a2912ffb1c512149e | Bin 0 -> 2392 bytes .../f968e146e317dbb5281aca4634de84461fd1ff82 | Bin 0 -> 1063 bytes .../fa1a1093d1da4f71b18d30481f09eeb7d61e6de1 | Bin 0 -> 296 bytes .../fa929c8218dd1b0676db695576a8f1a66067c685 | Bin 0 -> 304 bytes .../fba6554348b195a4752225342ded315662a11a99 | Bin 0 -> 234 bytes .../fc0f2acceb87b5396e0a10054b7ca35a2a124f38 | Bin 0 -> 470 bytes .../fcf1e81b7005c8aea37b5d8f0949a5d3048caf61 | Bin 0 -> 192 bytes .../fe9517d5de1d6e4b9d9fa9cc67e809b697e61886 | Bin 0 -> 191 bytes .../feb2a10cc688251772b52cbdf910f45130ed07db | Bin 0 -> 315 bytes .../fed06ee7931bb35a7cfdc9699f928df530bc2602 | Bin 0 -> 277 bytes .../ff01b583eddbccbe7c7ea08e7f83873310d91f0f | Bin 0 -> 543 bytes .../ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439 | Bin 0 -> 459 bytes external/boringssl/fuzz/spki.cc | 38 + .../04f58baf6e4bba0bb3094e2e26d3a531a7c263ee | Bin 0 -> 120 bytes .../079bdf85c086ad0a92bd01f1f70c645d81053f3a | Bin 0 -> 608 bytes .../0f5bd094b20a4632f14903bf62db8d467d2c548f | Bin 0 -> 162 bytes .../183c579d75863c1e10100f76e3ffb757b44a9587 | Bin 0 -> 91 bytes .../4ee178363e1d8411f30e540cb97d550d4ce62f0c | Bin 0 -> 444 bytes .../70da87d1d374ade329433dde31805abc8d80d915 | Bin 0 -> 302 bytes .../de0338b0c809548dc79d5a34e28b0010852a8f00 | Bin 0 -> 158 bytes .../fc941f77c710354d3c3c1426432a5ee935d51dd6 | Bin 0 -> 80 bytes external/boringssl/include/openssl/aead.h | 338 ++ external/boringssl/include/openssl/aes.h | 158 + external/boringssl/include/openssl/arm_arch.h | 121 + external/boringssl/include/openssl/asn1.h | 1114 ++++ external/boringssl/include/openssl/asn1_mac.h | 75 + external/boringssl/include/openssl/asn1t.h | 896 +++ external/boringssl/include/openssl/base.h | 298 + external/boringssl/include/openssl/base64.h | 187 + external/boringssl/include/openssl/bio.h | 918 ++++ external/boringssl/include/openssl/blowfish.h | 93 + external/boringssl/include/openssl/bn.h | 890 +++ external/boringssl/include/openssl/buf.h | 122 + external/boringssl/include/openssl/buffer.h | 18 + .../boringssl/include/openssl/bytestring.h | 394 ++ external/boringssl/include/openssl/cast.h | 96 + external/boringssl/include/openssl/chacha.h | 37 + external/boringssl/include/openssl/cipher.h | 571 ++ external/boringssl/include/openssl/cmac.h | 76 + external/boringssl/include/openssl/conf.h | 170 + external/boringssl/include/openssl/cpu.h | 173 + external/boringssl/include/openssl/crypto.h | 91 + .../boringssl/include/openssl/curve25519.h | 172 + external/boringssl/include/openssl/des.h | 177 + external/boringssl/include/openssl/dh.h | 267 + external/boringssl/include/openssl/digest.h | 267 + external/boringssl/include/openssl/dsa.h | 409 ++ external/boringssl/include/openssl/dtls1.h | 16 + external/boringssl/include/openssl/ec.h | 405 ++ external/boringssl/include/openssl/ec_key.h | 327 ++ external/boringssl/include/openssl/ecdh.h | 102 + external/boringssl/include/openssl/ecdsa.h | 206 + external/boringssl/include/openssl/engine.h | 98 + external/boringssl/include/openssl/err.h | 488 ++ external/boringssl/include/openssl/evp.h | 783 +++ external/boringssl/include/openssl/ex_data.h | 213 + external/boringssl/include/openssl/hkdf.h | 64 + external/boringssl/include/openssl/hmac.h | 158 + external/boringssl/include/openssl/lhash.h | 192 + .../boringssl/include/openssl/lhash_macros.h | 132 + external/boringssl/include/openssl/md4.h | 106 + external/boringssl/include/openssl/md5.h | 107 + external/boringssl/include/openssl/mem.h | 138 + external/boringssl/include/openssl/newhope.h | 147 + .../include/openssl/nid.h.REMOVED.git-id | 1 + external/boringssl/include/openssl/obj.h | 224 + external/boringssl/include/openssl/obj_mac.h | 18 + external/boringssl/include/openssl/objects.h | 18 + .../boringssl/include/openssl/opensslconf.h | 60 + external/boringssl/include/openssl/opensslv.h | 18 + external/boringssl/include/openssl/ossl_typ.h | 18 + external/boringssl/include/openssl/pem.h | 517 ++ external/boringssl/include/openssl/pkcs12.h | 18 + external/boringssl/include/openssl/pkcs7.h | 16 + external/boringssl/include/openssl/pkcs8.h | 224 + external/boringssl/include/openssl/poly1305.h | 51 + external/boringssl/include/openssl/pqueue.h | 146 + external/boringssl/include/openssl/rand.h | 122 + external/boringssl/include/openssl/rc4.h | 96 + external/boringssl/include/openssl/ripemd.h | 107 + external/boringssl/include/openssl/rsa.h | 664 +++ .../boringssl/include/openssl/safestack.h | 16 + external/boringssl/include/openssl/sha.h | 256 + external/boringssl/include/openssl/srtp.h | 18 + .../include/openssl/ssl.h.REMOVED.git-id | 1 + external/boringssl/include/openssl/ssl3.h | 435 ++ external/boringssl/include/openssl/stack.h | 295 + .../openssl/stack_macros.h.REMOVED.git-id | 1 + external/boringssl/include/openssl/thread.h | 184 + .../boringssl/include/openssl/time_support.h | 91 + external/boringssl/include/openssl/tls1.h | 680 +++ .../boringssl/include/openssl/type_check.h | 91 + external/boringssl/include/openssl/x509.h | 1267 +++++ external/boringssl/include/openssl/x509_vfy.h | 620 +++ external/boringssl/include/openssl/x509v3.h | 800 +++ external/boringssl/ssl/CMakeLists.txt | 92 + external/boringssl/ssl/custom_extensions.c | 257 + external/boringssl/ssl/d1_both.c | 851 +++ external/boringssl/ssl/d1_lib.c | 360 ++ external/boringssl/ssl/d1_meth.c | 131 + external/boringssl/ssl/d1_pkt.c | 416 ++ external/boringssl/ssl/d1_srtp.c | 233 + external/boringssl/ssl/dtls_record.c | 309 ++ external/boringssl/ssl/handshake_client.c | 2107 +++++++ external/boringssl/ssl/handshake_server.c | 2225 ++++++++ external/boringssl/ssl/internal.h | 1253 +++++ external/boringssl/ssl/pqueue/CMakeLists.txt | 22 + external/boringssl/ssl/pqueue/pqueue.c | 197 + external/boringssl/ssl/pqueue/pqueue_test.c | 129 + external/boringssl/ssl/s3_both.c | 551 ++ external/boringssl/ssl/s3_enc.c | 394 ++ external/boringssl/ssl/s3_lib.c | 375 ++ external/boringssl/ssl/s3_meth.c | 167 + external/boringssl/ssl/s3_pkt.c | 559 ++ external/boringssl/ssl/ssl_aead_ctx.c | 331 ++ external/boringssl/ssl/ssl_asn1.c | 718 +++ external/boringssl/ssl/ssl_buffer.c | 311 ++ external/boringssl/ssl/ssl_cert.c | 584 ++ external/boringssl/ssl/ssl_cipher.c | 2115 +++++++ external/boringssl/ssl/ssl_ecdh.c | 605 ++ external/boringssl/ssl/ssl_file.c | 585 ++ external/boringssl/ssl/ssl_lib.c | 2968 ++++++++++ external/boringssl/ssl/ssl_rsa.c | 428 ++ external/boringssl/ssl/ssl_session.c | 777 +++ external/boringssl/ssl/ssl_stat.c | 523 ++ external/boringssl/ssl/ssl_test.cc | 1386 +++++ external/boringssl/ssl/t1_enc.c | 562 ++ external/boringssl/ssl/t1_lib.c | 2743 ++++++++++ external/boringssl/ssl/test/CMakeLists.txt | 14 + external/boringssl/ssl/test/README.md | 35 + external/boringssl/ssl/test/async_bio.cc | 188 + external/boringssl/ssl/test/async_bio.h | 45 + external/boringssl/ssl/test/bssl_shim.cc | 1598 ++++++ external/boringssl/ssl/test/packeted_bio.cc | 304 + external/boringssl/ssl/test/packeted_bio.h | 51 + external/boringssl/ssl/test/runner/alert.go | 78 + external/boringssl/ssl/test/runner/cert.pem | 15 + .../ssl/test/runner/chacha20_poly1305.go | 235 + .../ssl/test/runner/chacha20_poly1305_test.go | 176 + .../ssl/test/runner/channel_id_key.pem | 5 + .../ssl/test/runner/cipher_suites.go | 508 ++ external/boringssl/ssl/test/runner/common.go | 1200 ++++ external/boringssl/ssl/test/runner/conn.go | 1451 +++++ .../ssl/test/runner/curve25519/const_amd64.s | 20 + .../ssl/test/runner/curve25519/cswap_amd64.s | 88 + .../ssl/test/runner/curve25519/curve25519.go | 841 +++ .../test/runner/curve25519/curve25519_test.go | 29 + .../ssl/test/runner/curve25519/doc.go | 23 + .../ssl/test/runner/curve25519/freeze_amd64.s | 94 + .../test/runner/curve25519/ladderstep_amd64.s | 1398 +++++ .../test/runner/curve25519/mont25519_amd64.go | 240 + .../ssl/test/runner/curve25519/mul_amd64.s | 191 + .../ssl/test/runner/curve25519/square_amd64.s | 153 + .../ssl/test/runner/deterministic.go | 37 + external/boringssl/ssl/test/runner/dtls.go | 446 ++ .../boringssl/ssl/test/runner/ecdsa_cert.pem | 12 + .../boringssl/ssl/test/runner/ecdsa_key.pem | 8 + .../ssl/test/runner/handshake_client.go | 1016 ++++ .../ssl/test/runner/handshake_messages.go | 1759 ++++++ .../ssl/test/runner/handshake_server.go | 1094 ++++ external/boringssl/ssl/test/runner/key.pem | 15 + .../ssl/test/runner/key_agreement.go | 1103 ++++ .../ssl/test/runner/newhope/newhope.go | 319 ++ .../ssl/test/runner/newhope/newhope_test.go | 154 + .../ssl/test/runner/newhope/reconciliation.go | 132 + .../ssl/test/runner/packet_adapter.go | 179 + .../ssl/test/runner/poly1305/const_amd64.s | 45 + .../ssl/test/runner/poly1305/poly1305.go | 32 + .../ssl/test/runner/poly1305/poly1305_amd64.s | 497 ++ .../ssl/test/runner/poly1305/poly1305_arm.s | 379 ++ .../ssl/test/runner/poly1305/poly1305_test.go | 86 + .../ssl/test/runner/poly1305/sum_amd64.go | 24 + .../ssl/test/runner/poly1305/sum_arm.go | 24 + .../ssl/test/runner/poly1305/sum_ref.go | 1531 ++++++ external/boringssl/ssl/test/runner/prf.go | 388 ++ .../ssl/test/runner/recordingconn.go | 167 + .../ssl/test/runner/runner.go.REMOVED.git-id | 1 + .../boringssl/ssl/test/runner/runner_test.go | 21 + .../boringssl/ssl/test/runner/test_output.go | 79 + external/boringssl/ssl/test/runner/ticket.go | 221 + external/boringssl/ssl/test/runner/tls.go | 279 + external/boringssl/ssl/test/scoped_types.h | 28 + external/boringssl/ssl/test/test_config.cc | 215 + external/boringssl/ssl/test/test_config.h | 114 + external/boringssl/ssl/tls_record.c | 471 ++ .../android-cmake/AndroidNdkGdb.cmake | 96 + .../android-cmake/AndroidNdkModules.cmake | 58 + .../third_party/android-cmake/LICENSE | 30 + .../third_party/android-cmake/README.google | 12 + .../third_party/android-cmake/README.md | 240 + .../android-cmake/android.toolchain.cmake | 1693 ++++++ .../third_party/android-cmake/ndk_links.md | 211 + external/boringssl/tool/CMakeLists.txt | 30 + external/boringssl/tool/args.cc | 104 + external/boringssl/tool/ciphers.cc | 66 + external/boringssl/tool/client.cc | 311 ++ external/boringssl/tool/const.cc | 434 ++ external/boringssl/tool/digest.cc | 478 ++ external/boringssl/tool/generate_ed25519.cc | 67 + external/boringssl/tool/genrsa.cc | 69 + external/boringssl/tool/internal.h | 92 + external/boringssl/tool/pkcs12.cc | 142 + external/boringssl/tool/rand.cc | 95 + external/boringssl/tool/server.cc | 152 + external/boringssl/tool/speed.cc | 632 +++ external/boringssl/tool/tool.cc | 126 + external/boringssl/tool/transport_common.cc | 333 ++ external/boringssl/tool/transport_common.h | 43 + .../boringssl/util/32-bit-toolchain.cmake | 7 + external/boringssl/util/all_tests.go | 319 ++ external/boringssl/util/all_tests.json | 70 + .../util/android-cmake/.gitattributes | 4 + .../boringssl/util/android-cmake/.gitignore | 41 + .../util/android-cmake/AndroidNdkGdb.cmake | 96 + .../android-cmake/AndroidNdkModules.cmake | 58 + .../boringssl/util/android-cmake/README.md | 240 + .../android-cmake/android.toolchain.cmake | 1693 ++++++ .../boringssl/util/android-cmake/ndk_links.md | 211 + external/boringssl/util/bot/DEPS | 141 + external/boringssl/util/bot/README | 3 + external/boringssl/util/bot/UPDATING | 47 + .../util/bot/cmake-linux64.tar.gz.sha1 | 1 + .../boringssl/util/bot/cmake-mac.tar.gz.sha1 | 1 + .../boringssl/util/bot/cmake-win32.zip.sha1 | 1 + external/boringssl/util/bot/extract.py | 139 + external/boringssl/util/bot/go/bootstrap.py | 296 + external/boringssl/util/bot/go/env.py | 49 + .../boringssl/util/bot/perl-win32.zip.sha1 | 1 + external/boringssl/util/bot/update_clang.py | 71 + external/boringssl/util/bot/vs_env.py | 37 + external/boringssl/util/bot/vs_toolchain.py | 113 + .../boringssl/util/bot/yasm-win32.exe.sha1 | 1 + external/boringssl/util/doc.config | 58 + external/boringssl/util/doc.css | 70 + external/boringssl/util/doc.go | 728 +++ external/boringssl/util/generate-asm-lcov.py | 152 + external/boringssl/util/generate-coverage.sh | 60 + .../boringssl/util/generate_build_files.py | 654 +++ external/boringssl/util/make_errors.go | 388 ++ external/boringssl/util/run_android_tests.go | 315 ++ external/cecil-legacy/.gitattributes | 1 + external/cecil-legacy/.gitignore | 10 + external/cecil-legacy/Mono.Cecil.Cil/Code.cs | 252 + .../cecil-legacy/Mono.Cecil.Cil/CodeReader.cs | 598 ++ .../cecil-legacy/Mono.Cecil.Cil/CodeWriter.cs | 649 +++ .../cecil-legacy/Mono.Cecil.Cil/Document.cs | 112 + .../Mono.Cecil.Cil/ExceptionHandler.cs | 89 + .../Mono.Cecil.Cil/ILProcessor.cs | 278 + .../Mono.Cecil.Cil/Instruction.cs | 321 ++ .../cecil-legacy/Mono.Cecil.Cil/MethodBody.cs | 241 + .../cecil-legacy/Mono.Cecil.Cil/OpCode.cs | 455 ++ .../cecil-legacy/Mono.Cecil.Cil/OpCodes.cs | 912 +++ .../Mono.Cecil.Cil/SequencePoint.cs | 70 + .../cecil-legacy/Mono.Cecil.Cil/Symbols.cs | 277 + .../Mono.Cecil.Cil/VariableDefinition.cs | 52 + .../Mono.Cecil.Cil/VariableReference.cs | 75 + .../Mono.Cecil.Metadata/BlobHeap.cs | 59 + .../Mono.Cecil.Metadata/Buffers.cs | 373 ++ .../Mono.Cecil.Metadata/CodedIndex.cs | 46 + .../Mono.Cecil.Metadata/ElementType.cs | 73 + .../Mono.Cecil.Metadata/GuidHeap.cs | 59 + .../cecil-legacy/Mono.Cecil.Metadata/Heap.cs | 48 + .../Mono.Cecil.Metadata/MetadataToken.cs | 105 + .../cecil-legacy/Mono.Cecil.Metadata/Row.cs | 170 + .../Mono.Cecil.Metadata/StringHeap.cs | 81 + .../Mono.Cecil.Metadata/TableHeap.cs | 111 + .../Mono.Cecil.Metadata/TokenType.cs | 56 + .../Mono.Cecil.Metadata/UserStringHeap.cs | 59 + .../Mono.Cecil.Metadata/Utilities.cs | 529 ++ .../Mono.Cecil.PE/BinaryStreamReader.cs | 51 + .../Mono.Cecil.PE/BinaryStreamWriter.cs | 96 + .../cecil-legacy/Mono.Cecil.PE/ByteBuffer.cs | 359 ++ .../ByteBufferEqualityComparer.cs | 78 + .../Mono.Cecil.PE/DataDirectory.cs | 50 + external/cecil-legacy/Mono.Cecil.PE/Image.cs | 166 + .../cecil-legacy/Mono.Cecil.PE/ImageReader.cs | 681 +++ .../cecil-legacy/Mono.Cecil.PE/ImageWriter.cs | 828 +++ .../cecil-legacy/Mono.Cecil.PE/Section.cs | 34 +- .../cecil-legacy/Mono.Cecil.PE/TextMap.cs | 129 + external/cecil-legacy/Mono.Cecil.csproj | 264 + external/cecil-legacy/Mono.Cecil.nunit | 9 + external/cecil-legacy/Mono.Cecil.nuspec | 23 + external/cecil-legacy/Mono.Cecil.sln | 197 + .../cecil-legacy/Mono.Cecil.sln.DotSettings | 35 + external/cecil-legacy/Mono.Cecil/ArrayType.cs | 159 + .../Mono.Cecil/AssemblyDefinition.cs | 189 + .../cecil-legacy/Mono.Cecil/AssemblyFlags.cs | 42 + .../Mono.Cecil/AssemblyHashAlgorithm.cs | 26 +- .../cecil-legacy/Mono.Cecil/AssemblyInfo.cs | 49 + .../Mono.Cecil/AssemblyLinkedResource.cs | 55 +- .../Mono.Cecil/AssemblyNameDefinition.cs | 35 +- .../Mono.Cecil/AssemblyNameReference.cs | 269 + .../cecil-legacy/Mono.Cecil/AssemblyReader.cs | 3233 +++++++++++ .../cecil-legacy/Mono.Cecil/AssemblyWriter.cs | 2576 +++++++++ .../Mono.Cecil/BaseAssemblyResolver.cs | 370 ++ external/cecil-legacy/Mono.Cecil/CallSite.cs | 124 + .../Mono.Cecil/CustomAttribute.cs | 232 + .../Mono.Cecil/DefaultAssemblyResolver.cs | 70 + .../Mono.Cecil/EmbeddedResource.cs | 105 + .../Mono.Cecil/EventAttributes.cs | 39 + .../Mono.Cecil/EventDefinition.cs | 168 + .../cecil-legacy/Mono.Cecil/EventReference.cs | 57 + .../cecil-legacy/Mono.Cecil/ExportedType.cs | 249 + .../Mono.Cecil/FieldAttributes.cs | 59 + .../Mono.Cecil/FieldDefinition.cs | 279 + .../cecil-legacy/Mono.Cecil/FieldReference.cs | 83 + .../cecil-legacy/Mono.Cecil/FileAttributes.cs | 35 + .../Mono.Cecil/FunctionPointerType.cs | 129 + .../Mono.Cecil/GenericInstanceMethod.cs | 85 + .../Mono.Cecil/GenericInstanceType.cs | 83 + .../Mono.Cecil/GenericParameter.cs | 287 + .../Mono.Cecil/GenericParameterAttributes.cs | 45 + .../Mono.Cecil/IConstantProvider.cs | 52 + .../Mono.Cecil/ICustomAttributeProvider.cs | 60 + .../Mono.Cecil/IGenericInstance.cs | 69 +- .../Mono.Cecil/IGenericParameterProvider.cs | 73 + .../Mono.Cecil/IMarshalInfoProvider.cs | 55 + .../Mono.Cecil/IMemberDefinition.cs | 100 + .../cecil-legacy/Mono.Cecil/IMetadataScope.cs | 41 + .../Mono.Cecil/IMetadataTokenProvider.cs | 35 + .../Mono.Cecil/IMethodSignature.cs | 75 + external/cecil-legacy/Mono.Cecil/Import.cs | 670 +++ .../cecil-legacy/Mono.Cecil/LinkedResource.cs | 60 + .../Mono.Cecil/ManifestResourceAttributes.cs | 39 + .../cecil-legacy/Mono.Cecil/MarshalInfo.cs | 171 + .../Mono.Cecil/MemberDefinitionCollection.cs | 92 + .../Mono.Cecil/MemberReference.cs | 101 + .../Mono.Cecil/MetadataResolver.cs | 381 ++ .../cecil-legacy/Mono.Cecil/MetadataSystem.cs | 395 ++ .../Mono.Cecil/MethodAttributes.cs | 66 + .../Mono.Cecil/MethodCallingConvention.cs | 40 + .../Mono.Cecil/MethodDefinition.cs | 487 ++ .../Mono.Cecil/MethodImplAttributes.cs | 53 + .../Mono.Cecil/MethodReference.cs | 214 + .../Mono.Cecil/MethodReturnType.cs | 104 + .../Mono.Cecil/MethodSemanticsAttributes.cs | 43 + .../Mono.Cecil/MethodSpecification.cs | 103 + external/cecil-legacy/Mono.Cecil/Modifiers.cs | 137 + .../Mono.Cecil/ModuleDefinition.cs | 1018 ++++ .../cecil-legacy/Mono.Cecil/ModuleKind.cs | 64 + .../Mono.Cecil/ModuleReference.cs | 67 + .../cecil-legacy/Mono.Cecil/NativeType.cs | 73 + .../Mono.Cecil/PInvokeAttributes.cs | 62 + .../cecil-legacy/Mono.Cecil/PInvokeInfo.cs | 138 + .../Mono.Cecil/ParameterAttributes.cs | 45 + .../Mono.Cecil/ParameterDefinition.cs | 172 + .../ParameterDefinitionCollection.cs | 80 + .../Mono.Cecil/ParameterReference.cs | 75 + .../cecil-legacy/Mono.Cecil/PinnedType.cs | 53 + .../cecil-legacy/Mono.Cecil/PointerType.cs | 61 + .../Mono.Cecil/PropertyAttributes.cs | 41 + .../Mono.Cecil/PropertyDefinition.cs | 265 + .../Mono.Cecil/PropertyReference.cs | 59 + .../cecil-legacy/Mono.Cecil/ReferenceType.cs | 61 + external/cecil-legacy/Mono.Cecil/Resource.cs | 76 + .../Mono.Cecil/SecurityDeclaration.cs | 191 + .../cecil-legacy/Mono.Cecil/SentinelType.cs | 53 + .../cecil-legacy/Mono.Cecil/TargetRuntime.cs | 25 +- .../cecil-legacy/Mono.Cecil/TypeAttributes.cs | 81 + .../cecil-legacy/Mono.Cecil/TypeDefinition.cs | 518 ++ .../Mono.Cecil/TypeDefinitionCollection.cs | 118 + .../cecil-legacy/Mono.Cecil/TypeParser.cs | 549 ++ .../cecil-legacy/Mono.Cecil/TypeReference.cs | 339 ++ .../Mono.Cecil/TypeSpecification.cs | 95 + .../cecil-legacy/Mono.Cecil/TypeSystem.cs | 290 + .../cecil-legacy/Mono.Cecil/VariantType.cs | 53 + .../Mono.Collections.Generic/Collection.cs | 420 ++ .../ReadOnlyCollection.cs | 112 + .../CryptoConvert.cs | 243 + .../CryptoService.cs | 177 + .../{cecil => cecil-legacy}/Mono/Actions.cs | 0 external/cecil-legacy/Mono/Empty.cs | 67 + .../{cecil => cecil-legacy}/Mono/Funcs.cs | 0 external/{cecil => cecil-legacy}/NOTES.txt | 0 .../ExtensionAttribute.cs | 0 .../{cecil => cecil-legacy}/Test/.gitignore | 0 .../cecil-legacy/Test/Mono.Cecil.Tests.csproj | 179 + .../Test/Mono.Cecil.Tests/Addin.cs | 0 .../Test/Mono.Cecil.Tests/AssemblyInfo.cs | 14 + .../Test/Mono.Cecil.Tests/AssemblyTests.cs | 35 + .../Test/Mono.Cecil.Tests/BaseTestFixture.cs | 76 + .../Mono.Cecil.Tests/CompilationService.cs | 237 + .../Mono.Cecil.Tests/CustomAttributesTests.cs | 519 ++ .../Test/Mono.Cecil.Tests/EventTests.cs | 66 + .../Test/Mono.Cecil.Tests/Extensions.cs | 92 + .../Test/Mono.Cecil.Tests/FieldTests.cs | 333 ++ .../Test/Mono.Cecil.Tests/Formatter.cs | 179 + .../Test/Mono.Cecil.Tests/ILProcessorTests.cs | 79 + .../Test/Mono.Cecil.Tests/ImageReadTests.cs | 144 + .../Test/Mono.Cecil.Tests/ImportCecilTests.cs | 374 ++ .../Mono.Cecil.Tests/ImportReflectionTests.cs | 409 ++ .../Test/Mono.Cecil.Tests/Linq.cs | 0 .../Test/Mono.Cecil.Tests/MethodBodyTests.cs | 412 ++ .../Test/Mono.Cecil.Tests/MethodTests.cs | 201 + .../Test/Mono.Cecil.Tests/ModuleTests.cs | 250 + .../Test/Mono.Cecil.Tests/NestedTypesTests.cs | 45 + .../Test/Mono.Cecil.Tests/ParameterTests.cs | 224 + .../Test/Mono.Cecil.Tests/PropertyTests.cs | 112 + .../Test/Mono.Cecil.Tests/ResolveTests.cs | 277 + .../SecurityDeclarationTests.cs | 290 + .../Test/Mono.Cecil.Tests/TypeParserTests.cs | 394 ++ .../Test/Mono.Cecil.Tests/TypeTests.cs | 228 + .../Test/Mono.Cecil.Tests/VariableTests.cs | 108 + .../Test/Resources/assemblies/moda.netmodule | Bin 0 -> 2048 bytes .../Test/Resources/assemblies/modb.netmodule | Bin 0 -> 2048 bytes .../Test/Resources/assemblies/text_file.txt | 1 + .../Test/Resources/cs/CustomAttributes.cs | 152 + .../cecil-legacy/Test/Resources/cs/Events.cs | 8 + .../cecil-legacy/Test/Resources/cs/Fields.cs | 41 + .../Test/Resources/cs/Generics.cs | 121 + .../Test/Resources/cs/Interfaces.cs | 22 + .../cecil-legacy/Test/Resources/cs/Layouts.cs | 16 + .../cecil-legacy/Test/Resources/cs/Methods.cs | 21 + .../Test/Resources/cs/NestedTypes.cs | 16 + .../Test/Resources/cs/Properties.cs | 18 + .../Test/Resources/il/explicitthis.il | 113 + .../cecil-legacy/Test/Resources/il/hello.il | 84 + .../Test/Resources/il/methodspecs.il | 43 + .../cecil-legacy/Test/Resources/il/others.il | 81 + .../cecil-legacy/Test/Resources/il/types.il | 58 + .../Test/libs/nunit-2.6.2/license.txt | 15 + .../{cecil => cecil-legacy}/dbg/Program.cs | 0 .../dbg/Properties/AssemblyInfo.cs | 0 .../{cecil => cecil-legacy}/dbg/dbg.csproj | 0 external/cecil-legacy/mono.snk | Bin 0 -> 596 bytes .../{cecil => cecil-legacy}/rocks/.gitignore | 0 .../rocks/Mono.Cecil.Rocks.csproj | 129 + .../rocks/Mono.Cecil.Rocks/AssemblyInfo.cs | 41 + .../rocks/Mono.Cecil.Rocks/Functional.cs | 59 + .../rocks/Mono.Cecil.Rocks/ILParser.cs | 236 + .../rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs | 407 ++ .../Mono.Cecil.Rocks/MethodDefinitionRocks.cs | 88 + .../Mono.Cecil.Rocks/ModuleDefinitionRocks.cs | 50 + .../ParameterReferenceRocks.cs | 11 + .../SecurityDeclarationRocks.cs | 174 + .../Mono.Cecil.Rocks/TypeDefinitionRocks.cs | 83 + .../Mono.Cecil.Rocks/TypeReferenceRocks.cs | 107 + .../rocks/Test/.gitignore | 0 .../rocks/Test/Mono.Cecil.Rocks.Tests.csproj | 106 + .../rocks/Test/Mono.Cecil.Tests/Addin.cs | 0 .../MethodDefinitionRocksTests.cs | 53 + .../ModuleDefinitionRocksTests.cs | 27 + .../SecurityDeclarationRocksTests.cs | 63 + .../TypeDefinitionRocksTests.cs | 97 + .../TypeReferenceRocksTests.cs | 124 + .../rocks/Test/Resources/cs/Types.cs | 14 + .../symbols/mdb/.gitignore | 0 .../symbols/mdb/Mono.Cecil.Mdb.csproj | 103 + .../mdb/Mono.Cecil.Mdb/AssemblyInfo.cs | 41 + .../symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs | 222 + .../symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs | 251 + .../MonoSymbolFile.cs | 738 +++ .../MonoSymbolTable.cs | 1376 +++++ .../MonoSymbolWriter.cs | 403 ++ .../SymbolWriterImpl.cs | 349 ++ .../symbols/mdb/Test/.gitignore | 0 .../mdb/Test/Mono.Cecil.Mdb.Tests.csproj | 119 + .../mdb/Test/Mono.Cecil.Tests/Addin.cs | 0 .../mdb/Test/Mono.Cecil.Tests/MdbTests.cs | 58 + .../Test/Resources/assemblies/hello.exe.mdb | Bin 0 -> 369 bytes .../symbols/pdb/.gitignore | 0 .../pdb/Microsoft.Cci.Pdb/BitAccess.cs | 255 + .../symbols/pdb/Microsoft.Cci.Pdb/BitSet.cs | 74 + .../symbols/pdb/Microsoft.Cci.Pdb/CvInfo.cs | 2435 +++++++++ .../pdb/Microsoft.Cci.Pdb/DataStream.cs | 111 + .../pdb/Microsoft.Cci.Pdb/DbiDbgHdr.cs | 41 + .../pdb/Microsoft.Cci.Pdb/DbiHeader.cs | 59 + .../pdb/Microsoft.Cci.Pdb/DbiModuleInfo.cs | 57 + .../pdb/Microsoft.Cci.Pdb/DbiSecCon.cs | 42 + .../pdb/Microsoft.Cci.Pdb/IntHashTable.cs | 583 ++ .../pdb/Microsoft.Cci.Pdb/Interfaces.cs | 77 + .../symbols/pdb/Microsoft.Cci.Pdb/LICENSE | 22 + .../pdb/Microsoft.Cci.Pdb/MsfDirectory.cs | 58 + .../pdb/Microsoft.Cci.Pdb/PdbConstant.cs | 89 + .../Microsoft.Cci.Pdb/PdbDebugException.cs | 20 + .../pdb/Microsoft.Cci.Pdb/PdbException.cs | 20 + .../symbols/pdb/Microsoft.Cci.Pdb/PdbFile.cs | 537 ++ .../pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs | 90 + .../pdb/Microsoft.Cci.Pdb/PdbFunction.cs | 498 ++ .../symbols/pdb/Microsoft.Cci.Pdb/PdbLine.cs | 29 + .../symbols/pdb/Microsoft.Cci.Pdb/PdbLines.cs | 23 + .../pdb/Microsoft.Cci.Pdb/PdbReader.cs | 40 + .../symbols/pdb/Microsoft.Cci.Pdb/PdbScope.cs | 122 + .../symbols/pdb/Microsoft.Cci.Pdb/PdbSlot.cs | 41 + .../pdb/Microsoft.Cci.Pdb/PdbSource.cs | 29 + .../pdb/Microsoft.Cci.Pdb/PdbTokenLine.cs | 33 + .../SourceLocationProvider.cs | 33 + .../symbols/pdb/Mono.Cecil.Pdb.csproj | 133 + .../pdb/Mono.Cecil.Pdb/AssemblyInfo.cs | 41 + .../ISymUnmanagedDocumentWriter.cs | 41 + .../Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs | 103 + .../pdb/Mono.Cecil.Pdb/ModuleMetadata.cs | 796 +++ .../symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs | 206 + .../symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs | 281 + .../symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs | 222 + .../pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs | 51 + .../symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs | 170 + .../symbols/pdb/Test/.gitignore | 0 .../pdb/Test/Mono.Cecil.Pdb.Tests.csproj | 124 + .../pdb/Test/Mono.Cecil.Tests/Addin.cs | 0 .../symbols/pdb/Test/Mono.Cecil.Tests/Linq.cs | 0 .../pdb/Test/Mono.Cecil.Tests/PdbTests.cs | 175 + .../Test/Resources/assemblies/VBConsApp.pdb | Bin 0 -> 36352 bytes .../pdb/Test/Resources/assemblies/fsapp.pdb | Bin 0 -> 11776 bytes .../pdb/Test/Resources/assemblies/test.pdb | Bin 0 -> 11776 bytes external/cecil/.gitattributes | 9 +- external/cecil/.gitignore | 5 + external/cecil/.travis.yml | 8 + external/cecil/LICENSE.txt | 21 + external/cecil/Mono.Cecil.Cil/Code.cs | 24 +- external/cecil/Mono.Cecil.Cil/CodeReader.cs | 241 +- external/cecil/Mono.Cecil.Cil/CodeWriter.cs | 71 +- external/cecil/Mono.Cecil.Cil/Document.cs | 28 +- .../cecil/Mono.Cecil.Cil/ExceptionHandler.cs | 24 +- external/cecil/Mono.Cecil.Cil/ILProcessor.cs | 24 +- external/cecil/Mono.Cecil.Cil/Instruction.cs | 42 +- external/cecil/Mono.Cecil.Cil/MethodBody.cs | 97 +- external/cecil/Mono.Cecil.Cil/OpCode.cs | 28 +- external/cecil/Mono.Cecil.Cil/OpCodes.cs | 24 +- external/cecil/Mono.Cecil.Cil/PortablePdb.cs | 409 ++ .../cecil/Mono.Cecil.Cil/SequencePoint.cs | 50 +- external/cecil/Mono.Cecil.Cil/Symbols.cs | 675 ++- .../Mono.Cecil.Cil/VariableDefinition.cs | 29 +- .../cecil/Mono.Cecil.Cil/VariableReference.cs | 39 +- .../cecil/Mono.Cecil.Metadata/BlobHeap.cs | 53 +- external/cecil/Mono.Cecil.Metadata/Buffers.cs | 85 +- .../cecil/Mono.Cecil.Metadata/CodedIndex.cs | 27 +- .../cecil/Mono.Cecil.Metadata/ElementType.cs | 24 +- .../cecil/Mono.Cecil.Metadata/GuidHeap.cs | 41 +- external/cecil/Mono.Cecil.Metadata/Heap.cs | 36 +- .../Mono.Cecil.Metadata/MetadataToken.cs | 33 +- external/cecil/Mono.Cecil.Metadata/PdbHeap.cs | 34 + external/cecil/Mono.Cecil.Metadata/Row.cs | 24 +- .../cecil/Mono.Cecil.Metadata/StringHeap.cs | 35 +- .../cecil/Mono.Cecil.Metadata/TableHeap.cs | 41 +- .../cecil/Mono.Cecil.Metadata/TokenType.cs | 35 +- .../Mono.Cecil.Metadata/UserStringHeap.cs | 35 +- .../cecil/Mono.Cecil.Metadata/Utilities.cs | 167 +- .../cecil/Mono.Cecil.PE/BinaryStreamReader.cs | 42 +- .../cecil/Mono.Cecil.PE/BinaryStreamWriter.cs | 24 +- external/cecil/Mono.Cecil.PE/ByteBuffer.cs | 56 +- .../ByteBufferEqualityComparer.cs | 24 +- external/cecil/Mono.Cecil.PE/DataDirectory.cs | 24 +- external/cecil/Mono.Cecil.PE/Image.cs | 115 +- external/cecil/Mono.Cecil.PE/ImageReader.cs | 196 +- external/cecil/Mono.Cecil.PE/ImageWriter.cs | 180 +- external/cecil/Mono.Cecil.PE/Section.cs | 25 +- external/cecil/Mono.Cecil.PE/TextMap.cs | 27 +- external/cecil/Mono.Cecil.Tests.props | 21 + external/cecil/Mono.Cecil.csproj | 265 +- external/cecil/Mono.Cecil.nunit | 12 +- external/cecil/Mono.Cecil.nuspec | 21 +- external/cecil/Mono.Cecil.props | 99 + external/cecil/Mono.Cecil.sln | 154 +- external/cecil/Mono.Cecil.sln.DotSettings | 4 + external/cecil/Mono.Cecil/ArrayType.cs | 24 +- .../cecil/Mono.Cecil/AssemblyDefinition.cs | 69 +- external/cecil/Mono.Cecil/AssemblyFlags.cs | 24 +- .../cecil/Mono.Cecil/AssemblyHashAlgorithm.cs | 24 +- external/cecil/Mono.Cecil/AssemblyInfo.cs | 33 +- .../Mono.Cecil/AssemblyLinkedResource.cs | 24 +- .../Mono.Cecil/AssemblyNameDefinition.cs | 24 +- .../cecil/Mono.Cecil/AssemblyNameReference.cs | 89 +- external/cecil/Mono.Cecil/AssemblyReader.cs | 962 +++- external/cecil/Mono.Cecil/AssemblyWriter.cs | 828 ++- .../cecil/Mono.Cecil/BaseAssemblyResolver.cs | 60 +- external/cecil/Mono.Cecil/CallSite.cs | 24 +- external/cecil/Mono.Cecil/CustomAttribute.cs | 56 +- .../Mono.Cecil/DefaultAssemblyResolver.cs | 38 +- external/cecil/Mono.Cecil/EmbeddedResource.cs | 51 +- external/cecil/Mono.Cecil/EventAttributes.cs | 24 +- external/cecil/Mono.Cecil/EventDefinition.cs | 45 +- external/cecil/Mono.Cecil/EventReference.cs | 31 +- external/cecil/Mono.Cecil/ExportedType.cs | 37 +- external/cecil/Mono.Cecil/FieldAttributes.cs | 24 +- external/cecil/Mono.Cecil/FieldDefinition.cs | 56 +- external/cecil/Mono.Cecil/FieldReference.cs | 33 +- external/cecil/Mono.Cecil/FileAttributes.cs | 24 +- .../cecil/Mono.Cecil/FunctionPointerType.cs | 26 +- .../cecil/Mono.Cecil/GenericInstanceMethod.cs | 26 +- .../cecil/Mono.Cecil/GenericInstanceType.cs | 26 +- external/cecil/Mono.Cecil/GenericParameter.cs | 40 +- .../Mono.Cecil/GenericParameterAttributes.cs | 24 +- .../cecil/Mono.Cecil/IConstantProvider.cs | 40 +- .../Mono.Cecil/ICustomAttributeProvider.cs | 30 +- external/cecil/Mono.Cecil/IGenericInstance.cs | 24 +- .../Mono.Cecil/IGenericParameterProvider.cs | 29 +- .../cecil/Mono.Cecil/IMarshalInfoProvider.cs | 27 +- .../cecil/Mono.Cecil/IMemberDefinition.cs | 24 +- external/cecil/Mono.Cecil/IMetadataScope.cs | 24 +- .../Mono.Cecil/IMetadataTokenProvider.cs | 24 +- external/cecil/Mono.Cecil/IMethodSignature.cs | 24 +- external/cecil/Mono.Cecil/Import.cs | 303 +- external/cecil/Mono.Cecil/LinkedResource.cs | 24 +- .../Mono.Cecil/ManifestResourceAttributes.cs | 24 +- external/cecil/Mono.Cecil/MarshalInfo.cs | 24 +- .../Mono.Cecil/MemberDefinitionCollection.cs | 26 +- external/cecil/Mono.Cecil/MemberReference.cs | 52 +- external/cecil/Mono.Cecil/MetadataResolver.cs | 61 +- external/cecil/Mono.Cecil/MetadataSystem.cs | 117 +- external/cecil/Mono.Cecil/MethodAttributes.cs | 24 +- .../Mono.Cecil/MethodCallingConvention.cs | 24 +- external/cecil/Mono.Cecil/MethodDefinition.cs | 134 +- .../cecil/Mono.Cecil/MethodImplAttributes.cs | 24 +- external/cecil/Mono.Cecil/MethodReference.cs | 33 +- external/cecil/Mono.Cecil/MethodReturnType.cs | 33 +- .../Mono.Cecil/MethodSemanticsAttributes.cs | 24 +- .../cecil/Mono.Cecil/MethodSpecification.cs | 26 +- external/cecil/Mono.Cecil/Modifiers.cs | 28 +- external/cecil/Mono.Cecil/ModuleDefinition.cs | 672 ++- external/cecil/Mono.Cecil/ModuleKind.cs | 30 +- external/cecil/Mono.Cecil/ModuleReference.cs | 24 +- external/cecil/Mono.Cecil/NativeType.cs | 24 +- .../cecil/Mono.Cecil/PInvokeAttributes.cs | 24 +- external/cecil/Mono.Cecil/PInvokeInfo.cs | 24 +- .../cecil/Mono.Cecil/ParameterAttributes.cs | 24 +- .../cecil/Mono.Cecil/ParameterDefinition.cs | 38 +- .../ParameterDefinitionCollection.cs | 24 +- .../cecil/Mono.Cecil/ParameterReference.cs | 24 +- external/cecil/Mono.Cecil/PinnedType.cs | 24 +- external/cecil/Mono.Cecil/PointerType.cs | 24 +- .../cecil/Mono.Cecil/PropertyAttributes.cs | 24 +- .../cecil/Mono.Cecil/PropertyDefinition.cs | 51 +- .../cecil/Mono.Cecil/PropertyReference.cs | 31 +- external/cecil/Mono.Cecil/ReferenceType.cs | 24 +- external/cecil/Mono.Cecil/Resource.cs | 24 +- .../cecil/Mono.Cecil/SecurityDeclaration.cs | 29 +- external/cecil/Mono.Cecil/SentinelType.cs | 24 +- external/cecil/Mono.Cecil/TargetRuntime.cs | 24 +- external/cecil/Mono.Cecil/Treatments.cs | 66 + external/cecil/Mono.Cecil/TypeAttributes.cs | 24 +- external/cecil/Mono.Cecil/TypeDefinition.cs | 209 +- .../Mono.Cecil/TypeDefinitionCollection.cs | 24 +- external/cecil/Mono.Cecil/TypeParser.cs | 101 +- external/cecil/Mono.Cecil/TypeReference.cs | 73 +- .../cecil/Mono.Cecil/TypeSpecification.cs | 26 +- external/cecil/Mono.Cecil/TypeSystem.cs | 135 +- external/cecil/Mono.Cecil/VariantType.cs | 24 +- .../Mono.Cecil/WindowsRuntimeProjections.cs | 875 +++ .../Mono.Collections.Generic/Collection.cs | 56 +- .../ReadOnlyCollection.cs | 28 +- .../CryptoConvert.cs | 20 +- .../CryptoService.cs | 41 +- external/cecil/Mono/Disposable.cs | 45 + external/cecil/Mono/Empty.cs | 41 +- external/cecil/Mono/Type.cs | 91 + external/cecil/ProjectInfo.cs | 22 + external/cecil/README.md | 23 + .../SHA1Managed.cs | 373 ++ external/cecil/Test/Mono.Cecil.Tests.csproj | 170 +- .../Test/Mono.Cecil.Tests/AssemblyInfo.cs | 8 - .../Test/Mono.Cecil.Tests/AssemblyTests.cs | 70 +- .../Test/Mono.Cecil.Tests/BaseTestFixture.cs | 279 +- .../Mono.Cecil.Tests/CompilationService.cs | 48 +- .../Mono.Cecil.Tests/CustomAttributesTests.cs | 493 +- .../cecil/Test/Mono.Cecil.Tests/EventTests.cs | 77 +- .../cecil/Test/Mono.Cecil.Tests/Extensions.cs | 3 +- .../cecil/Test/Mono.Cecil.Tests/FieldTests.cs | 635 ++- .../cecil/Test/Mono.Cecil.Tests/Formatter.cs | 13 +- .../Test/Mono.Cecil.Tests/ImageReadTests.cs | 187 +- .../Test/Mono.Cecil.Tests/ImportCecilTests.cs | 74 +- .../Mono.Cecil.Tests/ImportReflectionTests.cs | 122 +- .../Test/Mono.Cecil.Tests/MethodBodyTests.cs | 192 +- .../Test/Mono.Cecil.Tests/MethodTests.cs | 238 +- .../Test/Mono.Cecil.Tests/ModuleTests.cs | 290 +- .../Test/Mono.Cecil.Tests/NestedTypesTests.cs | 88 +- .../Test/Mono.Cecil.Tests/ParameterTests.cs | 196 +- .../Test/Mono.Cecil.Tests/PortablePdbTests.cs | 355 ++ .../Test/Mono.Cecil.Tests/PropertyTests.cs | 188 +- .../Test/Mono.Cecil.Tests/ResolveTests.cs | 17 +- .../SecurityDeclarationTests.cs | 134 +- .../Test/Mono.Cecil.Tests/TypeParserTests.cs | 12 +- .../cecil/Test/Mono.Cecil.Tests/TypeTests.cs | 280 +- .../Test/Mono.Cecil.Tests/VariableTests.cs | 22 +- .../WindowsRuntimeAssemblyResolver.cs | 93 + .../WindowsRuntimeProjectionsTests.cs | 141 + .../Resources/assemblies/ManagedWinmd.winmd | Bin 0 -> 8704 bytes .../Resources/assemblies/NativeWinmd.winmd | Bin 0 -> 3584 bytes .../Test/Resources/assemblies/PdbTarget.pdb | Bin 0 -> 1692 bytes .../assemblies/cecil.pdb.REMOVED.git-id | 1 + .../Test/Resources/assemblies/text_file.txt | 2 +- .../Test/Resources/assemblies/winrtcomp.winmd | Bin 0 -> 5120 bytes .../Test/Resources/cs/CustomAttributes.cs | 6 + .../cecil/Test/Resources/il/ca-empty-blob.il | 21 + .../cecil/Test/Resources/il/ca-iface-impl.il | 35 + external/cecil/Test/Resources/il/types.il | 12 - .../cecil/Test/libs/nunit-2.6.2/license.txt | 30 +- external/cecil/appveyor.yml | 13 + external/cecil/core/.vscode/launch.json | 22 + external/cecil/core/.vscode/tasks.json | 16 + external/cecil/core/project.json | 43 + external/cecil/rocks/Mono.Cecil.Rocks.csproj | 118 +- .../rocks/Mono.Cecil.Rocks/AssemblyInfo.cs | 31 +- .../rocks/Mono.Cecil.Rocks/DocCommentId.cs | 264 + .../rocks/Mono.Cecil.Rocks/Functional.cs | 24 +- .../cecil/rocks/Mono.Cecil.Rocks/ILParser.cs | 35 +- .../rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs | 24 +- .../Mono.Cecil.Rocks/MethodDefinitionRocks.cs | 26 +- .../Mono.Cecil.Rocks/ModuleDefinitionRocks.cs | 24 +- .../SecurityDeclarationRocks.cs | 28 +- .../Mono.Cecil.Rocks/TypeDefinitionRocks.cs | 24 +- .../Mono.Cecil.Rocks/TypeReferenceRocks.cs | 24 +- .../rocks/Test/Mono.Cecil.Rocks.Tests.csproj | 86 +- .../Mono.Cecil.Tests/DocCommentIdTests.cs | 264 + .../MethodDefinitionRocksTests.cs | 13 + .../ModuleDefinitionRocksTests.cs | 10 +- .../SecurityDeclarationRocksTests.cs | 48 +- .../TypeReferenceRocksTests.cs | 2 +- .../cecil/rocks/Test/Resources/cs/Types.cs | 0 .../cecil/symbols/mdb/Mono.Cecil.Mdb.csproj | 87 +- .../mdb/Mono.Cecil.Mdb/AssemblyInfo.cs | 31 +- .../symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs | 182 +- .../symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs | 169 +- .../MonoSymbolFile.cs | 197 +- .../MonoSymbolTable.cs | 212 +- .../MonoSymbolWriter.cs | 165 - .../SourceMethodBuilder.cs | 190 + .../mdb/Test/Mono.Cecil.Mdb.Tests.csproj | 99 +- .../mdb/Test/Mono.Cecil.Tests/MdbTests.cs | 60 +- .../BreakpointTest.Portable.dll.mdb | Bin 0 -> 865 bytes .../mscorlib.dll.mdb.REMOVED.git-id | 1 + .../symbols/pdb/Microsoft.Cci.Pdb/LICENSE | 0 .../pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs | 33 +- .../pdb/Microsoft.Cci.Pdb/PdbFunction.cs | 2 +- .../cecil/symbols/pdb/Mono.Cecil.Pdb.csproj | 121 +- .../pdb/Mono.Cecil.Pdb/AssemblyInfo.cs | 31 +- .../ISymUnmanagedDocumentWriter.cs | 21 +- .../Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs | 21 +- .../pdb/Mono.Cecil.Pdb/ModuleMetadata.cs | 2 +- .../symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs | 254 +- .../symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs | 208 +- .../symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs | 147 +- .../pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs | 21 +- .../symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs | 23 +- .../pdb/Test/Mono.Cecil.Pdb.Tests.csproj | 104 +- .../pdb/Test/Mono.Cecil.Tests/PdbTests.cs | 150 +- .../Test/Resources/assemblies/PdbTarget.pdb | Bin 0 -> 1692 bytes .../Test/Resources/assemblies/VBConsApp.pdb | Bin .../pdb/Test/Resources/assemblies/fsapp.pdb | Bin external/ikvm/reflect/Fusion.cs | 7 + external/ikvm/reflect/IKVM.Reflection.csproj | 2 +- .../src/framework/Assertion.cs | 169 + .../src/framework/Runner/TextUI.cs | 6 +- .../src/framework/StringAssert.cs | 227 + ikvm-native/Makefile.in | 13 +- libgc/os_dep.c.REMOVED.git-id | 2 +- llvm/Makefile.am | 30 + llvm/Makefile.in | 677 +++ llvm/SUBMODULES.json | 10 + m4/Makefile.in | 13 +- m4/nls.m4 | 2 +- man/Makefile.am | 1 + man/Makefile.in | 14 +- man/cert-sync.1 | 52 + man/mkbundle.1 | 279 +- man/mono.1 | 26 +- man/mprof-report.1 | 61 +- mcs/Makefile | 2 +- mcs/build/README.makefiles | 10 +- mcs/build/common/AssemblyRef.cs | 2 +- mcs/build/common/Consts.cs | 6 +- mcs/build/common/Consts.cs.in | 4 +- mcs/build/executable.make | 3 + mcs/build/library.make | 31 +- mcs/build/platforms/darwin.make | 2 - mcs/build/platforms/linux.make | 2 - mcs/build/platforms/win32.make | 3 - mcs/build/rules.make | 51 +- mcs/build/tests.make | 8 + .../Makefile | 2 - mcs/class/Facades/System.Data.Common/Makefile | 2 - .../System.Diagnostics.StackTrace/Makefile | 2 - .../System.Diagnostics.Tracing/Makefile | 2 - .../System.Diagnostics.Tracing.dll.sources | 1 - .../TypeForwarders.cs | 4 + .../System.Globalization.Extensions/Makefile | 2 - .../Makefile | 2 - mcs/class/Facades/System.Net.Sockets/Makefile | 2 - .../System.Net.Sockets.dll.sources | 3 - .../System.Net.Sockets/TypeForwarders.cs | 6 +- .../DynamicMethod.cs | 136 + ...em.Reflection.Emit.Lightweight.dll.sources | 2 +- .../TypeForwarders.cs | 3 +- .../System.Reflection.TypeExtensions/Makefile | 2 - .../Makefile | 2 - .../System.Runtime.Serialization.Xml/Makefile | 2 - .../System.Security.SecureString/Makefile | 2 - .../Makefile | 2 - .../CodePagesEncodingProvider.cs | 6 +- .../System.Text.Encoding.CodePages/Makefile | 2 - .../System.Threading.AccessControl/Makefile | 2 - .../System.Threading.Overlapped/Makefile | 2 - .../System.Xml.XPath.XDocument/Makefile | 2 - mcs/class/Facades/subdirs.make | 8 +- mcs/class/Makefile | 25 +- .../Microsoft.Build.Tasks/Vbc.cs | 5 +- .../ProjectRootElementTest.cs | 4 - .../ProjectCollectionTest.cs | 2 - .../Microsoft.Build.Evaluation/ToolsetTest.cs | 2 - .../ProjectTargetInstanceTest.cs | 2 - .../ProjectTaskInstanceTest.cs | 2 - .../DynamicContext.cs | 3 +- .../Microsoft.NuGet.Build.Tasks/Makefile | 13 +- .../Makefile | 11 +- .../Mono.Btls.Interface.dll.sources | 22 + .../Mono.Btls.Interface/BtlsObject.cs} | 65 +- .../Mono.Btls.Interface/BtlsProvider.cs | 107 + .../Mono.Btls.Interface/BtlsX509.cs | 132 + .../Mono.Btls.Interface/BtlsX509Chain.cs | 58 + .../Mono.Btls.Interface/BtlsX509Error.cs | 110 + .../Mono.Btls.Interface/BtlsX509Format.cs | 37 + .../Mono.Btls.Interface/BtlsX509Lookup.cs} | 61 +- .../Mono.Btls.Interface/BtlsX509Name.cs | 62 + .../Mono.Btls.Interface/BtlsX509Purpose.cs | 43 + .../Mono.Btls.Interface/BtlsX509Store.cs | 91 + .../Mono.Btls.Interface/BtlsX509StoreCtx.cs | 71 + .../BtlsX509StoreManager.cs | 44 + .../Mono.Btls.Interface/BtlsX509StoreType.cs} | 30 +- .../Mono.Btls.Interface/BtlsX509TrustKind.cs | 42 + .../BtlsX509VerifyFlags.cs | 38 + .../BtlsX509VerifyParam.cs | 91 + .../Mono.Btls.Interface/VersionInfo.cs | 34 + .../Properties/AssemblyInfo.cs | 11 +- .../Mono.CSharp/Mono.CSharp_test.dll.sources | 1 + .../Test/Evaluator/ExpressionsTest.cs | 5 +- .../Mono.CSharp/Test/Visit/ASTVisitorTest.cs | 60 + .../mobile_static_Mono.CSharp.dll.sources | 9 - mcs/class/Mono.CSharp/monotouch.cs | 304 - .../monotouch_Mono.CSharp.dll.sources | 1 - .../monotouch_tv_Mono.CSharp.dll.sources | 1 - .../monotouch_watch_Mono.CSharp.dll.sources | 1 - .../Mono.Cecil.Mdb/Mono.Cecil.Mdb.dll.sources | 10 +- mcs/class/Mono.Cecil/Makefile | 2 +- mcs/class/Mono.Cecil/Mono.Cecil.dll.sources | 136 +- mcs/class/Mono.CodeContracts/Makefile | 2 +- .../CompileVisitor.cs | 6 +- .../SourcePositionVisitor.cs | 3 + .../ContractsRuntime.cs | 2 +- .../Mono.CodeContracts.Static.AST/TypeNode.cs | 2 +- .../Mono.CodeContracts/Test/TestCCRewrite.cs | 4 +- .../SourceMethodBuilder.cs | 53 +- .../SymbolWriterImpl.cs | 2 +- mcs/class/Mono.Data.Sqlite/Makefile | 2 +- mcs/class/Mono.Data.Sqlite/resources/SR.resx | 6 +- mcs/class/Mono.Debugger.Soft/Makefile | 7 +- .../Mono.Debugger.Soft.dll.sources | 1 + .../Mono.Debugger.Soft/Connection.cs | 17 +- .../Mono.Debugger.Soft/LocalScope.cs | 35 + .../Mono.Debugger.Soft/MethodMirror.cs | 13 + .../Mono.Debugger.Soft/Test/dtest-app.cs | 54 +- .../Test/dtest.cs.REMOVED.git-id | 2 +- .../Mono.Security.Providers.DotNet/Makefile | 14 - ...Mono.Security.Providers.DotNet.dll.sources | 6 - .../DotNetSslStreamImpl.cs | 317 -- .../DotNetTlsProvider.cs | 118 - .../Mono.Security.Providers.DotNet/README.md | 1 - .../Makefile | 24 - ...rity.Providers.NewSystemSource.dll.sources | 33 - .../Properties/AssemblyInfo.cs | 48 - .../README.md | 95 - .../Mono.Security.Providers.NewTls/Makefile | 12 - ...Mono.Security.Providers.NewTls.dll.sources | 13 - .../MonoNewTlsStream.cs | 93 - .../MonoNewTlsStreamFactory.cs | 91 - .../NewTlsProvider.cs | 95 - .../TlsContextWrapper.cs | 221 - .../TlsProviderFactory.cs | 97 - .../Properties/AssemblyInfo.cs | 47 - ...Mono.Security.Providers.NewTls.dll.sources | 7 - ...Mono.Security.Providers.NewTls.dll.sources | 1 - .../OldTlsProvider.cs | 87 - .../Mono.Security/Assembly/AssemblyInfo.cs | 7 +- .../CertificateValidationHelper.cs | 19 +- .../CipherSuiteCode.cs | 1 + .../MonoTlsConnectionInfo.cs | 5 + .../MonoTlsProvider.cs | 34 +- .../MonoTlsProviderFactory.cs | 122 +- .../MonoTlsSettings.cs | 1 + .../Mono.Security.Protocol.Tls/DebugHelper.cs | 2 +- .../Mono.Security.X509/X509Store.cs | 63 +- .../Mono.Security.X509/X509StoreManager.cs | 56 +- .../Mono.Security.X509/X509Stores.cs | 18 +- .../Mono.Security/Mono.Security.dll.sources | 1 - .../Test/Mono.Math/BigIntegerSetTest.cs | 2 +- .../Test/Mono.Math/PrimeTestingTest.cs | 18 +- .../Test/Mono.Math/SearchGeneratorTest.cs | 4 +- .../PrivateKeyTest.cs | 54 +- .../CryptoConvertTest.cs | 56 +- .../DiffieHellmanManagedTest.cs | 10 +- .../Mono.Security.Cryptography/PKCS8Test.cs | 60 +- .../ChallengeResponseTest.cs | 26 +- .../MessageBaseTest.cs | 4 +- .../Type1MessageTest.cs | 22 +- .../Type2MessageTest.cs | 18 +- .../Type3MessageTest.cs | 48 +- .../Test/Mono.Security/StrongNameTest.cs | 46 +- mcs/class/Mono.Tasklets/Makefile | 4 +- .../Mono.Tasklets_test.dll.sources | 1 + .../Test/Mono.Tasklets/ContinuationsTest.cs | 189 + mcs/class/Novell.Directory.Ldap/Makefile | 17 +- .../SMDiagnostics/Assembly/AssemblyInfo.cs | 2 +- .../Makefile | 10 +- .../CompareAttributeTest.cs | 2 - .../CreditCardAttributeTest.cs | 2 - .../EmailAddressAttributeTest.cs | 2 - .../FileExtensionsAttributeTest.cs | 2 - .../PhoneAttributeTest.cs | 2 - .../System.Core/Assembly/AssemblyInfo.cs | 2 +- .../SafeNCryptHandle.cs | 4 +- .../AnonymousPipeServerStream.cs | 6 +- .../System.IO.Pipes/NamedPipeClientStream.cs | 12 +- .../System.IO.Pipes/NamedPipeServerStream.cs | 11 +- .../System.Core/System.IO.Pipes/PipeStream.cs | 29 +- .../RSACertificateExtensions.cs | 10 +- .../AesTransform.cs | 2 +- .../System.Security.Cryptography/MD5Cng.cs | 2 +- .../System.Security.Cryptography/SHA1Cng.cs | 2 +- .../System.Security.Cryptography/SHA256Cng.cs | 2 +- .../SHA256CryptoServiceProvider.cs | 2 +- .../System.Security.Cryptography/SHA384Cng.cs | 2 +- .../SHA384CryptoServiceProvider.cs | 2 +- .../System.Security.Cryptography/SHA512Cng.cs | 2 +- .../SHA512CryptoServiceProvider.cs | 2 +- .../common_System.Core.dll.sources | 1 - .../System.Data.Services.Client/Makefile | 8 +- mcs/class/System.Data/Makefile | 10 +- .../ReferenceSources/PoolBlockingPeriod.cs | 9 + .../ReferenceSources/Res.cs.REMOVED.git-id | 2 +- .../SqlBulkCopy.platformnotsupported.cs | 136 + .../System.Data.SqlClient/SqlCommand.cs | 93 +- .../SqlCommand.platformnotsupported.cs | 277 + .../SqlCommandBuilder.platformnotsupported.cs | 158 + .../System.Data.SqlClient/SqlConnection.cs | 16 +- .../SqlConnection.platformnotsupported.cs | 214 + .../SqlDataReader.platformnotsupported.cs | 363 ++ .../SqlException.platformnotsupported.cs | 102 + .../SqlParameter.platformnotsupported.cs | 198 + ...arameterCollection.platformnotsupported.cs | 216 + .../SqlTransaction.platformnotsupported.cs | 77 + .../System.Data.Common/DbDataAdapterTest.cs | 4 + .../System.Data.Common/DbDataReaderTest.cs | 2 - .../System.Data.SqlClient/SqlBulkCopyTest.cs | 24 + .../SqlCommandBuilderTest.cs | 45 + .../System.Data.SqlClient/SqlCommandTest.cs | 66 + .../SqlConnectionTest.cs | 123 +- .../SqlDataAdapterTest.cs | 36 + .../System.Data.SqlClient/SqlParameterTest.cs | 141 + .../System.Data/ConstraintCollectionTest2.cs | 2 +- .../Test/System.Data/DataRowTest.cs | 211 +- .../Test/System.Data/DataRowViewTest.cs | 28 +- .../System.Data/DataTableCollectionTest.cs | 134 +- .../DataTableTest.cs.REMOVED.git-id | 2 +- .../Test/System.Data/DataViewManagerTest.cs | 26 +- .../Test/System.Data/DataViewTest.cs | 198 +- .../System.Data/ForeignKeyConstraintTest.cs | 139 +- .../Test/System.Xml/XmlDataDocumentTest2.cs | 58 +- .../mobile_System.Data.dll.sources | 1 + ...ouch_watch_System.Data.dll.exclude.sources | 11 + .../monotouch_watch_System.Data.dll.sources | 9 + .../net_4_x_System.Data.dll.sources | 1 + .../Test/System.IO.Compression/ZipTest.cs | 18 + mcs/class/System.IO.Compression/ZipArchive.cs | 6 + .../System.IO.Compression/ZipArchiveEntry.cs | 2 +- .../Assembly/AssemblyInfo.cs | 5 +- mcs/class/System.IdentityModel/Makefile | 6 +- .../BinarySecretSecurityToken.cs | 0 .../InternalEncryptedKeyIdentifierClause.cs | 0 .../WrappedKeySecurityToken.cs | 0 .../BinarySecretKeyIdentifierClause.cs | 0 .../KeyNameIdentifierClause.cs | 0 .../SecurityContextKeyIdentifierClause.cs | 0 .../BootstrapContextTest.cs | 2 - .../net_4_x_System.IdentityModel.dll.sources | 6 + mcs/class/System.Json.Microsoft/Makefile | 9 +- mcs/class/System.Net.Http.Formatting/Makefile | 15 +- .../ContentRangeHeaderValue.cs | 6 +- .../System.Net.Http.Headers/HeaderInfo.cs | 11 +- .../HttpHeaderValueCollection.cs | 27 +- .../System.Net.Http.Headers/HttpHeaders.cs | 23 +- .../System.Net.Http/HttpClientHandler.cs | 4 +- .../HttpClientHandler.platformnotsupported.cs | 175 + .../HttpHeaderValueCollection.cs | 37 + .../System.Net.Http/HttpClientHandlerTest.cs | 12 + .../Test/System.Net.Http/HttpClientTest.cs | 77 + ..._watch_System.Net.Http.dll.exclude.sources | 1 + ...onotouch_watch_System.Net.Http.dll.sources | 2 + mcs/class/System.Net/Assembly/AssemblyInfo.cs | 2 +- .../ReferenceSources/SRef.cs | 31 - .../System.Runtime.Caching.dll.sources | 2 +- .../Assembly/AssemblyInfo.cs | 2 +- .../Test/InternalSoapValuesTest.cs | 2 +- .../Test/SerializationTest.cs | 2 +- .../Test/SoapFormatterTest.cs | 66 +- .../Assembly/AssemblyInfo.cs | 2 +- .../System.Runtime.Serialization/Makefile | 4 +- .../LocalAppContextSwitches.cs | 7 + .../ReferenceSources/SchemaExporter_mobile.cs | 6 +- .../XsdDataContractExporter_mobile.cs | 54 + .../System.Runtime.Serialization.dll.sources | 1 + .../DataContractResolverTest.cs | 2 + .../XmlObjectSerializerTest.cs | 4 + ...e_System.Runtime.Serialization.dll.sources | 1 + mcs/class/System.Security/Makefile | 9 +- .../Assembly/AssemblyInfo.cs | 2 +- .../Assembly/AssemblyInfo.cs | 2 +- .../Assembly/AssemblyInfo.cs | 2 +- .../Assembly/AssemblyInfo.cs | 4 +- .../WebMessageEncoder.cs | 6 +- .../WebMessageEncodingBindingElement.cs | 6 +- .../WebHttpBehavior.cs | 12 +- .../WebMessageFormatter.cs | 18 +- .../WebChannelFactory.cs | 4 +- .../WebOperationContext.cs | 12 +- .../System.ServiceModel/WebHttpBinding.cs | 6 +- .../System.ServiceModel/WebHttpSecurity.cs | 2 +- .../Assembly/AssemblyInfo.cs | 15 +- .../Mono.CodeGeneration/CodeModule.cs | 2 +- .../Mono.Security.Protocol.Tls/DebugHelper.cs | 2 +- .../BinaryMessageEncodingBindingElement.cs | 4 +- .../System.ServiceModel.Channels/Binding.cs | 4 +- .../BindingContext.cs | 4 +- .../BindingElement.cs | 4 +- .../ChannelManagerBase.cs | 2 +- .../FaultConverter.cs | 2 +- .../HttpRequestChannel.cs | 7 +- .../HttpTransportBindingElement.cs | 8 +- .../HttpsTransportBindingElement.cs | 4 +- .../LocalClientSecuritySettings.cs | 4 +- .../MessageBufferImpl.cs | 2 +- .../MessageEncodingBindingElement.cs | 2 +- .../MessageHeader.cs | 6 +- .../MessageHeaders.cs | 2 +- .../MessageProperties.cs | 2 +- .../ReliableSessionBindingElement.cs | 2 +- .../SecurityBindingElement.cs | 22 +- .../TextMessageEncodingBindingElement.cs | 4 +- .../TransportBindingElement.cs | 4 +- .../TransportSecurityBindingElement.cs | 4 +- .../ClientCredentials.cs | 10 +- .../ContractDescriptionGenerator.cs | 4 +- ...DataContractSerializerOperationBehavior.cs | 8 +- .../MessagePartDescription.cs | 2 +- .../XmlSerializerOperationBehavior.cs | 4 +- .../MessageLoggingSettings.cs | 2 +- .../BaseMessagesFormatter.cs | 10 +- .../ClientOperation.cs | 2 +- .../ClientRuntime.cs | 6 +- .../DispatchOperation.cs | 6 +- .../DispatchRuntime.cs | 4 +- ...509CertificateInitiatorClientCredential.cs | 4 +- ...509CertificateRecipientClientCredential.cs | 8 +- .../System.ServiceModel.dll.sources | 6 - .../BasicHttpBinding_4_5.cs | 10 +- .../System.ServiceModel/BasicHttpsBinding.cs | 8 +- .../System.ServiceModel/ChannelFactory.cs | 6 +- .../ClientProxyGenerator.cs | 4 +- .../System.ServiceModel/ClientRealProxy.cs | 2 +- .../DuplexClientRuntimeChannel.cs | 4 - .../System.ServiceModel/EndpointAddress.cs | 12 +- .../System.ServiceModel/EndpointAddress10.cs | 2 +- .../EndpointAddressBuilder.cs | 2 +- .../System.ServiceModel/Logger.cs | 16 +- .../System.ServiceModel/OperationContext.cs | 6 +- .../SilverlightClientConfigLoader.cs | 2 +- .../System.ServiceModel_test.dll.sources | 1 - .../Test/MetadataTests/ImportTests.cs | 2 - .../Test/MetadataTests/MetadataSamples.cs | 2 - .../CommunicationObjectSyncTest.cs | 38 +- ...ac_net_4_5_System.ServiceModel.dll.sources | 1 - .../TransformBlockTest.cs | 4 +- mcs/class/System.Web.Http.SelfHost/Makefile | 11 +- mcs/class/System.Web.Http.WebHost/Makefile | 12 +- mcs/class/System.Web.Http/Makefile | 17 +- mcs/class/System.Web.Mvc3/Makefile | 10 +- mcs/class/System.Web.Razor/Makefile | 14 +- .../System.Web.WebPages.Deployment/Makefile | 16 +- mcs/class/System.Web.WebPages.Razor/Makefile | 14 +- mcs/class/System.Web.WebPages/Makefile | 16 +- mcs/class/System.Web/Makefile | 7 +- .../FormsAuthentication.cs | 11 +- mcs/class/System.Web/System.Web.dll.sources | 1 + mcs/class/System.Web/System.Web/HttpCookie.cs | 13 + .../System.Web.Security/MachineKeyTest.cs | 2 - .../MembershipPasswordAttributeTest.cs | 2 - .../EventHandlerTaskAsyncHelperTest.cs | 2 - .../System.Web/HttpTaskAsyncHandlerTest.cs | 2 - .../Test/System.Web/TaskAsyncResultTest.cs | 2 - .../System.Windows.Forms/Application.cs | 4 +- .../DateTimePickerTest.cs.REMOVED.git-id | 2 +- mcs/class/System.XML/Assembly/AssemblyInfo.cs | 4 +- mcs/class/System.XML/Makefile | 2 +- .../LocalAppContextSwitches.cs | 9 +- .../XmlChoiceIdentifierAttribute.cs | 2 +- .../XmlCustomFormatter.cs | 29 +- .../XmlMemberMapping.cs | 2 +- .../XmlReflectionImporter.cs | 4 +- .../XmlSerializationReader.cs | 23 + .../System.Xml.Serialization/XmlSerializer.cs | 17 +- .../XmlSerializerFactory.cs | 5 + .../XslCompiledTransform_Mobile.cs | 15 + .../DeserializeTests.cs | 7 + .../XmlSerializationWriterTests.cs | 18 +- .../XmlSerializerTestClasses.cs | 6 + .../Test/System.Xml/XmlReaderCommonTests.cs | 4 - .../Test/System.Xml/XmlReaderSettingsTests.cs | 2 - .../Test/System.Xml/XmlResolverTest.cs | 2 - .../Test/System.Xml/XmlSecureResolverTests.cs | 2 - .../Test/System.Xml/XmlUrlResolverTests.cs | 4 - .../Test/System.Xml/XmlWriterSettingsTests.cs | 4 - .../System.Xaml/Assembly/AssemblyInfo.cs | 2 +- .../System.Xaml/TypeExtensionMethods.cs | 2 +- .../System.Xml.Linq/Assembly/AssemblyInfo.cs | 2 +- .../XElementTest.cs.REMOVED.git-id | 2 +- mcs/class/System/Assembly/AssemblyInfo.cs | 15 +- mcs/class/System/Makefile | 39 +- .../SafeX509ChainHandle.cs | 17 +- mcs/class/System/Mono.Btls/MonoBtlsBio.cs | 449 ++ mcs/class/System/Mono.Btls/MonoBtlsContext.cs | 454 ++ mcs/class/System/Mono.Btls/MonoBtlsError.cs | 83 + .../System/Mono.Btls/MonoBtlsException.cs | 53 + mcs/class/System/Mono.Btls/MonoBtlsKey.cs | 104 + mcs/class/System/Mono.Btls/MonoBtlsObject.cs | 149 + mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs | 145 + .../System/Mono.Btls/MonoBtlsProvider.cs | 295 + mcs/class/System/Mono.Btls/MonoBtlsSsl.cs | 418 ++ mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs | 260 + .../MonoBtlsSslError.cs} | 42 +- mcs/class/System/Mono.Btls/MonoBtlsStream.cs | 65 + mcs/class/System/Mono.Btls/MonoBtlsUtils.cs | 187 + mcs/class/System/Mono.Btls/MonoBtlsX509.cs | 465 ++ .../System/Mono.Btls/MonoBtlsX509Chain.cs | 122 + mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs | 185 + .../System/Mono.Btls/MonoBtlsX509Error.cs | 111 + .../System/Mono.Btls/MonoBtlsX509Exception.cs | 56 + .../System/Mono.Btls/MonoBtlsX509FileType.cs | 37 + .../System/Mono.Btls/MonoBtlsX509Format.cs | 36 + .../System/Mono.Btls/MonoBtlsX509Lookup.cs | 213 + .../Mono.Btls/MonoBtlsX509LookupAndroid.cs} | 37 +- .../Mono.Btls/MonoBtlsX509LookupMono.cs | 128 + .../MonoBtlsX509LookupMonoCollection.cs | 102 + .../Mono.Btls/MonoBtlsX509LookupType.cs | 39 + .../System/Mono.Btls/MonoBtlsX509Name.cs | 216 + .../Mono.Btls/MonoBtlsX509NameEntryType.cs | 51 + .../System/Mono.Btls/MonoBtlsX509Purpose.cs | 43 + .../System/Mono.Btls/MonoBtlsX509Revoked.cs | 120 + .../System/Mono.Btls/MonoBtlsX509Store.cs | 230 + .../System/Mono.Btls/MonoBtlsX509StoreCtx.cs | 244 + .../Mono.Btls/MonoBtlsX509StoreManager.cs | 120 + .../System/Mono.Btls/MonoBtlsX509StoreType.cs | 40 + .../System/Mono.Btls/MonoBtlsX509TrustKind.cs | 42 + .../Mono.Btls/MonoBtlsX509VerifyFlags.cs | 39 + .../Mono.Btls/MonoBtlsX509VerifyParam.cs | 277 + .../Mono.Btls/X509CertificateImplBtls.cs | 495 ++ .../System/Mono.Btls/X509ChainImplBtls.cs | 178 + .../ChainValidationHelper.cs | 59 +- .../Mono.Net.Security/IMonoTlsProvider.cs | 7 - .../Mono.Net.Security/LegacySslStream.cs | 2 +- ...acyTlsProvider.cs => LegacyTlsProvider.cs} | 50 +- .../Mono.Net.Security/MobileTlsContext.cs | 43 +- .../MonoTlsProviderFactory.Droid.cs | 10 +- .../MonoTlsProviderFactory.cs | 148 +- .../Mono.Net.Security/MonoTlsProviderImpl.cs | 108 - .../MonoTlsProviderWrapper.cs | 13 - .../System/Mono.Net.Security/MonoTlsStream.cs | 1 - .../Mono.Net.Security/NoReflectionHelper.cs | 48 +- .../SystemCertificateValidator.cs | 12 +- .../AutoWebProxyScriptEngine.cs | 181 + mcs/class/System/ReferenceSources/HttpApi.cs | 2 +- mcs/class/System/ReferenceSources/Internal.cs | 80 - .../LocalAppContextSwitches.cs | 7 + mcs/class/System/ReferenceSources/Logging.cs | 22 +- .../System/ReferenceSources/NativeMethods.cs | 9 + .../ReferenceSources/RequestCacheProtocol.cs | 10 + mcs/class/System/ReferenceSources/SR2.cs | 6 +- .../ReferenceSources/SSPISafeHandles.cs | 208 - .../System/ReferenceSources/SSPIWrapper.cs | 303 - .../ReferenceSources/SecureStringHelper.cs | 47 + .../SettingsSectionInternal.cs | 11 + mcs/class/System/ReferenceSources/Socket.cs | 45 + .../System/ReferenceSources/SslStream.cs | 141 - .../SystemNetworkCredential.cs | 13 - .../System/ReferenceSources/_SecureChannel.cs | 41 - .../System/ReferenceSources/_SslState.cs | 141 - .../System/ReferenceSources/_SslStream.cs | 230 - .../System.Diagnostics/FileVersionInfo.cs | 6 +- .../ProcessThreadCollection.cs | 113 - .../System.IO.Compression/DeflateStream.cs | 6 +- .../System.IO/FileSystemWatcher_mobile.cs | 18 +- .../WebRequestModuleHandler.cs | 14 +- .../System/System.Net.Mail/MailMessage.cs | 7 +- .../System/System.Net.Mail/SmtpClient.cs | 11 +- .../SmtpClient.platformnotsupported.cs | 167 + .../NetworkChange.cs | 2 +- .../NetworkInterface.cs | 44 + .../System.Net.Security/EncryptionPolicy.cs | 2 - .../LocalCertificateSelectionCallback.cs | 2 +- .../System.Net.Security/NegotiateStream.cs | 48 + .../RemoteCertificateValidationCallback.cs | 3 - .../System.Net.Security/SslPolicyErrors.cs | 2 - .../System/System.Net.Security/SslStream.cs | 3 - .../SslStream.platformnotsupported.cs | 287 + .../Socket.cs.REMOVED.git-id | 2 +- .../SocketAsyncEventArgs.cs | 46 +- .../SocketReceiveFromResult.cs | 6 +- .../SocketReceiveMessageFromResult.cs | 6 +- .../SocketTaskExtensions.cs | 6 +- .../TcpClient.platformnotsupported.cs | 191 + .../System/System.Net.Sockets/TcpListener.cs | 24 +- .../TcpListener.platformnotsupported.cs | 135 + .../System/System.Net.Sockets/UdpClient.cs | 8 + .../UdpClient.platformnotsupported.cs | 241 + .../ClientWebSocket.platformnotsupported.cs | 98 + .../System.Net/AuthenticationManager.cs | 9 +- ...henticationManager.platformnotsupported.cs | 77 + .../System/System.Net/CredentialCache.cs | 282 - mcs/class/System/System.Net/Dns.cs | 24 + ...FtpRequestCreator.platformnotsupported.cs} | 25 +- mcs/class/System/System.Net/FtpWebRequest.cs | 153 +- .../FtpWebRequest.platformnotsupported.cs | 182 + .../FtpWebResponse.platformnotsupported.cs | 91 + .../System/System.Net/GlobalProxySelection.cs | 83 - mcs/class/System/System.Net/HttpListener.cs | 60 + .../HttpListener.platformnotsupported.cs | 123 + .../System/System.Net/HttpListenerContext.cs | 9 + ...ttpListenerContext.platformnotsupported.cs | 68 + ...erPrefixCollection.platformnotsupported.cs | 93 + ...ttpListenerRequest.platformnotsupported.cs | 180 + .../System/System.Net/HttpListenerResponse.cs | 80 +- ...tpListenerResponse.platformnotsupported.cs | 150 + .../System.Net/HttpListenerResponseHelper.cs | 88 + .../System.Net/HttpListenerTimeoutManager.cs | 40 + mcs/class/System/System.Net/HttpWebRequest.cs | 45 +- .../HttpWebRequest.platformnotsupported.cs | 422 ++ .../System/System.Net/HttpWebResponse.cs | 2 +- .../HttpWebResponse.platformnotsupported.cs | 147 + .../System/System.Net/NetworkCredential.cs | 112 - mcs/class/System/System.Net/ServicePoint.cs | 5 + .../ServicePoint.platformnotsupported.cs | 127 + .../System/System.Net/ServicePointManager.cs | 29 +- ...ervicePointManager.platformnotsupported.cs | 129 + mcs/class/System/System.Net/WebConnection.cs | 45 +- mcs/class/System/System.Net/WebProxy.cs | 252 - mcs/class/System/System.Net/WebRequest.cs | 548 -- .../SemaphoreSecurity.cs | 2 +- .../OSX509Certificates.cs | 9 +- .../X500DistinguishedName.cs | 3 +- .../X509Certificate2.cs | 12 +- .../X509Certificate2Impl.cs | 4 + .../X509Certificate2ImplMono.cs | 5 + .../X509ChainPolicy.cs | 3 + .../X509Helper2.cs | 133 +- .../System/System.Threading/Semaphore.cs | 221 - mcs/class/System/System.dll.sources | 99 +- mcs/class/System/System/AndroidPlatform.cs | 32 + mcs/class/System/System/UriTypeConverter.cs | 16 +- .../InstanceDescriptorTest.cs | 4 +- .../CategoryAttributeTests.cs | 2 +- .../FileVersionInfoTest.cs.REMOVED.git-id | 2 +- .../Test/System.Diagnostics/ProcessTest.cs | 21 + .../DeflateStreamTest.cs | 42 +- .../System.IO.Compression/GzipStreamTest.cs | 2 - .../Test/System.Net.Mail/SmtpClientTest.cs | 78 +- .../Test/System.Net.Security/SslStreamTest.cs | 3 + .../System.Net.Sockets/NetworkStreamTest.cs | 8 + .../SocketAcceptAsyncTest.cs | 45 +- .../System.Net.Sockets/SocketAsyncTest.cs | 34 +- .../SocketTest.cs.REMOVED.git-id | 2 +- .../Test/System.Net.Sockets/TcpClientTest.cs | 16 + .../System.Net.Sockets/TcpListenerTest.cs | 27 + .../Test/System.Net.Sockets/UdpClientTest.cs | 121 + .../ClientWebSocketTest.cs | 42 +- .../Test/System.Net/CookieParserTest.cs | 44 +- mcs/class/System/Test/System.Net/DnsTest.cs | 107 +- .../Test/System.Net/FtpWebRequestTest.cs | 317 +- .../Test/System.Net/HttpListener2Test.cs | 116 +- .../HttpListenerPrefixCollectionTest.cs | 66 + .../System.Net/HttpListenerRequestTest.cs | 15 + .../Test/System.Net/HttpListenerTest.cs | 155 +- .../HttpWebRequestTest.cs.REMOVED.git-id | 2 +- .../Test/System.Net/HttpWebResponseTest.cs | 90 + .../Test/System.Net/NetworkCredentialTest.cs | 16 + .../System.Net/ServicePointManagerTest.cs | 9 +- .../Test/System.Net/ServicePointTest.cs | 84 +- .../System/Test/System.Net/WebClientTest.cs | 27 +- .../Test/System.Net/WebClientTestAsync.cs | 2 - .../System.Net/WebHeaderCollectionTest.cs | 6 + .../System/Test/System.Net/WebProxyTest.cs | 5 - .../System/Test/System.Net/WebRequestTest.cs | 73 +- .../Test/System.Threading/SemaphoreTest.cs | 9 + .../System/Test/System/UriPermutationsTest.cs | 4 - mcs/class/System/Test/System/UriTest.cs | 25 - mcs/class/System/Test/System/UriTest3.cs | 2 + mcs/class/System/mobile_System.dll.sources | 96 +- mcs/class/System/monodroid_System.dll.sources | 1 + ...onotouch_watch_System.dll.exclude.sources} | 150 +- .../System/monotouch_watch_System.dll.sources | 19 + ...h_watch_runtime_System.dll.exclude.sources | 1 + ...monotouch_watch_runtime_System.dll.sources | 2 +- mcs/class/corlib/Assembly/AssemblyInfo.cs | 4 +- mcs/class/corlib/CommonCrypto/SecRandom.cs | 12 + mcs/class/corlib/Makefile | 2 +- .../corlib/Microsoft.Win32/IRegistryApi.cs | 4 +- .../RegistryKeyPermissionCheck.cs | 2 +- .../corlib/Microsoft.Win32/UnixRegistryApi.cs | 4 +- .../Microsoft.Win32/Win32RegistryApi.cs | 121 +- .../corlib/Microsoft.Win32/Win32ResultCode.cs | 5 +- mcs/class/corlib/Mono.Security/Uri.cs | 4 +- mcs/class/corlib/Mono/Runtime.cs | 21 +- mcs/class/corlib/Mono/RuntimeHandles.cs | 274 + mcs/class/corlib/Mono/RuntimeMarshal.cs | 65 + mcs/class/corlib/Mono/RuntimeStructs.cs | 83 + mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs | 38 + mcs/class/corlib/Mono/SafeStringMarshal.cs | 46 + .../ReferenceSources/AppContextSwitches.cs | 4 +- .../corlib/ReferenceSources/MethodBase.cs | 16 +- .../corlib/ReferenceSources/PathInternal.cs | 10 + .../corlib/ReferenceSources/RuntimeType.cs | 114 +- .../corlib/ReferenceSources/SharedStatics.cs | 22 - .../EventCounter.cs | 6 +- .../System.Diagnostics.Tracing/EventSource.cs | 2 + .../corlib/System.Diagnostics/StackFrame.cs | 19 +- .../corlib/System.Diagnostics/StackTrace.cs | 4 + .../System.Globalization/CultureInfo.cs | 45 +- mcs/class/corlib/System.IO/Directory.cs | 4 +- mcs/class/corlib/System.IO/DirectoryInfo.cs | 17 +- mcs/class/corlib/System.IO/File.cs | 9 - mcs/class/corlib/System.IO/FileStream.cs | 16 +- mcs/class/corlib/System.IO/MonoIO.cs | 8 +- mcs/class/corlib/System.IO/MonoIOError.cs | 4 +- mcs/class/corlib/System.IO/Path.cs | 16 +- .../System.Reflection.Emit/AssemblyBuilder.cs | 26 +- .../AssemblyBuilder.pns.cs | 69 + .../AssemblyBuilderAccess.cs | 2 - .../ConstructorBuilder.cs | 14 +- .../ConstructorBuilder.pns.cs | 92 + .../CustomAttributeBuilder.pns.cs} | 45 +- .../System.Reflection.Emit/EnumBuilder.cs | 5 + .../System.Reflection.Emit/EnumBuilder.pns.cs | 117 + .../EventBuilder.pns.cs} | 54 +- .../System.Reflection.Emit/FieldBuilder.cs | 8 + .../FieldBuilder.pns.cs} | 95 +- .../GenericTypeParameterBuilder.pns.cs | 115 + .../System.Reflection.Emit/ILGenerator.pns.cs | 229 + .../corlib/System.Reflection.Emit/Label.cs | 2 - .../System.Reflection.Emit/LocalBuilder.cs | 14 +- .../System.Reflection.Emit/MethodBuilder.cs | 19 +- .../MethodBuilder.pns.cs | 112 + .../ModuleBuilder.pns.cs | 122 + .../ParameterBuilder.pns.cs | 92 + .../PropertyBuilder.pns.cs | 108 + .../System.Reflection.Emit/SignatureHelper.cs | 2 + .../SignatureHelper.pns.cs | 116 + .../System.Reflection.Emit/TypeBuilder.cs | 68 +- .../System.Reflection.Emit/TypeBuilder.pns.cs | 284 + .../UnmanagedMarshal.cs | 2 +- .../corlib/System.Reflection/Assembly.cs | 54 +- .../corlib/System.Reflection/AssemblyName.cs | 81 +- .../corlib/System.Reflection/EventInfo.cs | 23 +- .../corlib/System.Reflection/MonoAssembly.cs | 15 + .../corlib/System.Reflection/MonoMethod.cs | 4 +- .../corlib/System.Reflection/MonoModule.cs | 4 +- .../corlib/System.Reflection/MonoProperty.cs | 2 +- .../corlib/System.Reflection/PropertyInfo.cs | 13 + .../System.Reflection/StrongNameKeyPair.cs | 2 +- .../System.Runtime.InteropServices/Marshal.cs | 34 +- .../SafeHandle.cs | 4 +- .../_Assembly.cs | 4 +- .../ActivationServices.cs | 2 +- .../MonoMethodMessage.cs | 55 +- .../RealProxy.cs | 80 +- .../RemotingConfiguration.cs | 23 +- .../RemotingServices.cs | 2 +- .../corlib/System.Runtime/GCLatencyMode.cs | 3 +- .../NativeObjectSecurity.cs | 5 + .../X509Certificate.cs | 2 +- .../X509ContentType.cs | 2 +- .../X509Helper.cs | 4 +- .../X509KeyStorageFlags.cs | 2 +- ...toConfig_2_1.cs => CryptoConfig.common.cs} | 0 .../CryptoConfig.cs | 33 +- .../CryptoConfig.fullaot.cs | 34 + .../IncrementalHash.cs | 2 +- .../RNGCryptoServiceProvider.cs | 6 +- .../RSACryptoServiceProvider.cs | 48 +- .../CodeAccessSecurityAttribute.cs | 2 +- .../EnvironmentPermissionAttribute.cs | 2 +- .../FileIOPermissionAttribute.cs | 2 +- .../HostProtectionAttribute.cs | 2 +- .../PermissionSetAttribute.cs | 4 +- .../ReflectionPermissionAttribute.cs | 2 +- .../SecurityAction.cs | 2 +- .../SecurityAttribute.cs | 2 +- .../SecurityPermissionAttribute.cs | 4 +- .../SecurityPermissionFlag.cs | 2 +- .../StrongNamePermissionAttribute.cs | 2 +- .../corlib/System.Security.Policy/Evidence.cs | 6 +- .../System.Security.Policy/PolicyLevel.cs | 2 +- .../corlib/System.Security.Policy/Zone.cs | 8 +- .../corlib/System.Security/SecurityManager.cs | 2 +- .../System.Threading/EventWaitHandle.cs | 235 - mcs/class/corlib/System.Threading/Mutex.cs | 2 +- .../System.Threading/NativeEventCalls.cs | 4 +- mcs/class/corlib/System.Threading/Thread.cs | 80 +- mcs/class/corlib/System/AppDomain.cs | 33 +- mcs/class/corlib/System/AppDomainSetup.cs | 28 +- mcs/class/corlib/System/CStreamReader.cs | 2 +- mcs/class/corlib/System/CStreamWriter.cs | 2 +- mcs/class/corlib/System/Console.cs | 10 +- mcs/class/corlib/System/ConsoleDriver.cs | 2 +- mcs/class/corlib/System/Environment.cs | 36 +- mcs/class/corlib/System/GC.cs | 159 - mcs/class/corlib/System/NullConsoleDriver.cs | 2 +- mcs/class/corlib/System/Nullable.cs | 4 +- mcs/class/corlib/System/RuntimeTypeHandle.cs | 4 + mcs/class/corlib/System/TermInfoDriver.cs | 2 +- mcs/class/corlib/System/TermInfoNumbers.cs | 2 +- mcs/class/corlib/System/TermInfoReader.cs | 2 +- mcs/class/corlib/System/TermInfoStrings.cs | 2 +- mcs/class/corlib/System/TimeZoneInfo.cs | 8 +- mcs/class/corlib/System/WeakReference.cs | 2 +- .../corlib/System/WindowsConsoleDriver.cs | 2 +- .../RegistryKeyTest.cs.REMOVED.git-id | 2 +- .../ComparerTest.cs | 2 - .../Test/System.Collections/SortedListTest.cs | 2 +- .../System.Globalization/CultureInfoTest.cs | 33 +- .../IsolatedStorageFileTest.cs | 16 +- .../Test/System.IO/DirectoryInfoTest.cs | 6 + .../corlib/Test/System.IO/FileInfoTest.cs | 4 +- .../System.IO/FileStreamSafeHandleTest.cs | 2 +- .../corlib/Test/System.IO/FileStreamTest.cs | 11 - .../corlib/Test/System.IO/MemoryStreamTest.cs | 4 - mcs/class/corlib/Test/System.IO/PathTest.cs | 12 + .../corlib/Test/System.IO/StreamReaderTest.cs | 4 - mcs/class/corlib/Test/System.IO/StreamTest.cs | 2 - .../corlib/Test/System.IO/StreamWriterTest.cs | 2 - .../MethodBuilderTest.cs | 2 +- .../System.Reflection/AssemblyNameTest.cs | 2 - .../Test/System.Reflection/AssemblyTest.cs | 366 +- .../IntrospectionExtensionsTest.cs | 2 - .../Test/System.Reflection/ModuleTest.cs | 23 +- .../System.Reflection/MonoGenericClassTest.cs | 2 +- .../System.Reflection/ParameterInfoTest.cs | 14 +- .../System.Reflection/PropertyInfoTest.cs | 7 +- .../System.Resources/ResourceReaderTest.cs | 12 +- .../AsyncVoidMethodBuilderTest.cs | 2 - .../TaskAwaiterTest.cs | 2 - .../TaskAwaiterTest_T.cs | 2 - .../YieldAwaitableTest.cs | 2 - .../MarshalTest.cs | 162 +- .../RuntimeEnvironmentTest.cs | 2 +- .../ClaimsIdentityTest.cs | 2 - .../ClaimsPrincipalTest.cs | 2 - .../X509CapiTest.cs | 4 +- .../CryptoConfigTest.cs | 12 +- .../CryptoStreamTest.cs | 2 +- .../DSACryptoServiceProviderTest.cs | 2 +- .../HashAlgorithmTest.cs | 4 +- .../PasswordDeriveBytesTest.cs | 12 +- .../RNGCryptoServiceProviderTest.cs | 2 +- ...ryptoServiceProviderTest.cs.REMOVED.git-id | 2 +- .../RijndaelManagedTest.cs | 4 +- .../SignatureDescriptionTest.cs | 30 +- .../Test/System.Security.Policy/ZoneTest.cs | 2 +- .../HostSecurityManagerTest.cs | 4 +- .../ConcurrentExclusiveSchedulerPairTest.cs | 2 - .../Test/System.Threading.Tasks/TaskTest.cs | 4 - .../CancellationTokenSourceTest.cs | 6 - .../System.Threading/EventWaitHandleTest.cs | 12 + .../Test/System.Threading/ThreadTest.cs | 41 +- .../Test/System.Threading/VolatileTest.cs | 2 - .../corlib/Test/System/AppDomainSetupTest.cs | 105 +- .../System/AppDomainTest.cs.REMOVED.git-id | 2 +- .../corlib/Test/System/ArraySegmentTest.cs | 2 - mcs/class/corlib/Test/System/AttributeTest.cs | 31 +- .../corlib/Test/System/BitConverterTest.cs | 2 +- mcs/class/corlib/Test/System/ConsoleTest.cs | 2 - .../Test/System/ConvertTest.cs.REMOVED.git-id | 2 +- mcs/class/corlib/Test/System/DelegateTest.cs | 14 +- mcs/class/corlib/Test/System/DoubleTest.cs | 1 + .../corlib/Test/System/EnvironmentTest.cs | 4 +- mcs/class/corlib/Test/System/GCTest.cs | 72 + .../corlib/Test/System/TimeZoneInfoTest.cs | 15 + .../Test/System/TypeTest.cs.REMOVED.git-id | 2 +- .../corlib/Test/System/WeakReferenceTest.cs | 2 - mcs/class/corlib/coreclr/AsyncLocal.cs | 115 - .../DisablePrivateReflectionAttribute.cs | 17 - mcs/class/corlib/coreclr/EncodingProvider.cs | 136 - mcs/class/corlib/coreclr/FormattableString.cs | 80 - .../coreclr/FormattableStringFactory.cs | 57 - .../corlib/coreclr/WaitHandleExtensions.cs | 45 - mcs/class/corlib/corlib.dll.sources | 59 +- mcs/class/corlib/corlib_test.dll.sources | 3 +- .../monotouch_runtime_corlib.dll.sources | 16 +- .../corlib/monotouch_tv_corlib.dll.sources | 16 +- .../monotouch_tv_runtime_corlib.dll.sources | 16 +- .../corlib/monotouch_watch_corlib.dll.sources | 16 +- ...monotouch_watch_runtime_corlib.dll.sources | 16 +- mcs/class/corlib/net_4_x_corlib.dll.sources | 1 - .../Compiler/DebugInfoGenerator.cs | 4 + mcs/class/doc/NUnitGuidelines | 32 +- mcs/class/legacy/Mono.Cecil/Makefile | 14 + .../legacy/Mono.Cecil/Mono.Cecil.dll.sources | 127 + .../monolite/Mono.Security.dll.REMOVED.git-id | 2 +- .../System.Configuration.dll.REMOVED.git-id | 2 +- .../monolite/System.Core.dll.REMOVED.git-id | 2 +- .../System.Security.dll.REMOVED.git-id | 2 +- .../monolite/System.Xml.dll.REMOVED.git-id | 2 +- .../lib/monolite/System.dll.REMOVED.git-id | 2 +- .../lib/monolite/basic.exe.REMOVED.git-id | 2 +- .../lib/monolite/mscorlib.dll.REMOVED.git-id | 2 +- .../FlowchartConnectionPointsAdorner.cs | 6 +- .../Presentation/Xaml/ViewStateXamlHelper.cs | 124 +- .../Activities/Hosting/WorkflowInstance.cs | 14 + .../WorkflowApplication.cs.REMOVED.git-id | 2 +- .../LocalAppContextSwitches.cs | 2 + .../RegularExpressionAttribute.cs | 20 +- .../Clr/inc/AppContextDefaultValues.cs | 11 + .../InternalApis/Clr/inc/LocalAppContext.cs | 10 + .../System/Configuration/ClientConfigPaths.cs | 15 +- .../Win32/SafeHandles/CapiSafeHandles.cs | 32 +- .../Security/Cryptography/BCryptNative.cs | 33 + .../Security/Cryptography/CapiNative.cs | 10 + .../Cryptography/CapiSymmetricAlgorithm.cs | 3 + .../Security/Cryptography/ECDiffieHellman.cs | 97 +- .../Cryptography/ECDiffieHellmanCng.cs | 111 +- .../Cryptography/ECDiffieHellmanPublicKey.cs | 6 +- .../System/Security/Cryptography/ECDsaCng.cs | 57 +- .../Security/Cryptography/NCryptNative.cs | 57 +- .../System/Security/Cryptography/RsaCng.cs | 42 +- .../RSACertificateExtensions.cs | 8 +- .../ReaderWriterLockSlim.cs | 6 - .../Data/Common/Utils/MetadataHelper.cs | 2 + .../EntityModel/SchemaObjectModel/Schema.cs | 1 + .../XmlILOptimizerVisitor.cs.REMOVED.git-id | 2 +- .../Data/Common/DbConnectionStringCommon.cs | 139 + .../System/Data/DataSet.cs.REMOVED.git-id | 2 +- .../System/Data/DataTable.cs.REMOVED.git-id | 2 +- .../Data/ProviderBase/DbConnectionPool.cs | 84 +- .../Data/SqlClient/SqlClientSymmetricKey.cs | 34 +- .../SqlClient/SqlCommand.cs.REMOVED.git-id | 2 +- .../SqlClient/SqlConnection.cs.REMOVED.git-id | 2 +- .../Data/SqlClient/SqlConnectionString.cs | 30 + .../SqlClient/SqlConnectionStringBuilder.cs | 38 + .../SqlConnectionTimeoutErrorInternal.cs | 16 +- ...SqlInternalConnectionTds.cs.REMOVED.git-id | 2 +- .../System/Data/SqlClient/SqlParameter.cs | 3 - .../Data/SqlClient/SqlSymmetricKeyCache.cs | 21 +- .../System/Data/SqlClient/SqlUtil.cs | 2 +- .../System/Data/SqlClient/TdsEnums.cs | 3 + .../System/NewXml/XPathNodePointer.cs | 1 - .../Clr/inc/AppContextDefaultValues.cs | 11 + .../InternalApis/Clr/inc/LocalAppContext.cs | 10 + .../Claims/X509CertificateClaimSet.cs | 194 +- .../IdentityModel/LocalAppContextSwitches.cs | 15 + .../Tokens/X509AsymmetricSecurityKey.cs | 64 +- .../System/Caching/CacheMemoryMonitor.cs | 10 +- .../System/Caching/MemoryCache.cs | 48 +- .../System/Caching/MemoryCacheStatistics.cs | 21 +- .../System/Caching/SRef.cs | 85 + .../DataContract.cs.REMOVED.git-id | 2 +- .../Serialization/Diagnostics/TraceUtility.cs | 2 + .../Json/DataContractJsonSerializer.cs | 2 + .../Json/JsonClassDataContract.cs | 2 + .../Serialization/Json/JsonDataContract.cs | 2 + .../Json/JsonEncodingStreamWrapper.cs | 2 + .../Json/JsonObjectDataContract.cs | 2 + .../Serialization/Json/JsonReaderDelegator.cs | 2 + .../Json/JsonReaderWriterFactory.cs | 2 + .../Serialization/Json/JsonWriterDelegator.cs | 22 +- .../Serialization/Json/XmlJsonReader.cs | 2 + .../Serialization/Json/XmlJsonWriter.cs | 2 + ...lObjectSerializerReadContextComplexJson.cs | 2 + ...ObjectSerializerWriteContextComplexJson.cs | 2 + .../Runtime/Serialization/SchemaExporter.cs | 2 +- .../Runtime/Serialization/SchemaImporter.cs | 2 +- .../XmlObjectSerializerReadContext.cs | 2 + .../XmlObjectSerializerWriteContext.cs | 2 + .../Serialization/XmlSerializableServices.cs | 2 - .../Activation/HostedAspNetEnvironment.cs | 13 +- .../Runtime/Diagnostics/EtwDiagnosticTrace.cs | 1 + .../Clr/inc/AppContextDefaultValues.cs | 11 + .../InternalApis/Clr/inc/LocalAppContext.cs | 10 + .../AppContextDefaultValues.Default.cs | 5 + .../Channels/HttpChannelListener.cs | 8 +- .../Channels/PipeConnection.cs.REMOVED.git-id | 2 +- .../Channels/TransportDefaults.cs | 4 +- .../Channels/UnsafeNativeMethods.cs | 81 +- .../ServiceModel/Channels/WebSocketHelper.cs | 2 + .../Properties.cs.REMOVED.git-id | 2 +- .../Description/MessageContractExporter.cs | 19 +- .../ServiceModel/Description/WsdlHelper.cs | 5 +- .../ServiceModel/Dispatcher/QueryMatcher.cs | 2 + .../Dispatcher/TaskMethodInvoker.cs | 347 +- .../XmlSerializerOperationFormatter.cs | 2 +- .../System/ServiceModel/EndpointAddress10.cs | 2 +- .../ServiceModel/EndpointAddressAugust2004.cs | 2 +- .../ServiceModel/LocalAppContextSwitches.cs | 21 + .../System/ServiceModel/OperationContext.cs | 39 +- .../ServiceModel/OperationContextScope.cs | 15 +- .../ServiceModel/Security/CryptoHelper.cs | 3 + .../ServiceModel/Security/SecurityUtils.cs | 2393 -------- .../Security/SecurityUtils.cs.REMOVED.git-id | 1 + .../Security/TlsSspiNegotiation.cs | 9 +- .../Tokens/IssuedSecurityTokenProvider.cs | 2 +- .../WSSecurityPolicy.cs.REMOVED.git-id | 2 +- .../System/ServiceModel/Security/WSTrust.cs | 2 +- .../WSTrustServiceContract.cs.REMOVED.git-id | 2 +- .../System/ServiceModel/ServiceHost.cs | 5 +- .../ServiceModel/ServiceModelAppSettings.cs | 18 + .../System.ServiceModel/System/UriTemplate.cs | 24 +- .../DynamicData/DynamicValidator.cs | 3 +- .../DynamicData/FieldTemplateUserControl.cs | 6 +- .../DynamicData/MetaColumn.cs | 11 +- .../WCFModel/DataSvcMapFileLoader.cs | 2 + .../Compilation/WCFModel/MetadataFile.cs | 3 + .../Compilation/WCFModel/SvcMapFileLoader.cs | 2 + .../Adapters/ChtmlCalendarAdapter.cs | 2 +- .../Adapters/WmlCalendarAdapter.cs | 2 +- .../System.Web/AspNetEventSource.cs | 8 + .../System.Web/Cache/CacheDependency.cs | 20 +- .../referencesource/System.Web/Cache/SRef.cs | 3 +- .../referencesource/System.Web/Cache/cache.cs | 84 +- .../BuildManager.cs.REMOVED.git-id | 2 +- .../Compilation/PreservationFileReader.cs | 1 + .../Compilation/XsdBuildProvider.cs | 1 + .../BrowserCapabilitiesCodeGenerator.cs | 3 + .../HttpCapabilitiesSectionHandler.cs | 3 +- .../RemoteWebConfigurationHostServer.cs | 2 + .../Handlers/TransferRequestHandler.cs | 36 +- .../System.Web/Hosting/ApplicationManager.cs | 24 +- .../System.Web/Hosting/HostingEnvironment.cs | 5 + .../HttpApplication.cs.REMOVED.git-id | 2 +- .../System.Web/HttpCacheParams.cs | 25 +- .../System.Web/HttpCachePolicy.cs | 208 +- .../System.Web/HttpCacheVary.cs | 32 +- .../HttpCacheVaryByContentEncodings.cs | 25 +- .../referencesource/System.Web/HttpContext.cs | 19 +- .../System.Web/HttpResponse.cs.REMOVED.git-id | 2 +- .../DataAnnotationsModelMetadataProvider.cs | 14 +- .../DataAnnotationsModelValidator.cs | 53 +- .../DataAnnotationsModelValidatorProvider.cs | 15 +- .../ModelBinding/RangeAttributeAdapter.cs | 5 + .../RegularExpressionAttributeAdapter.cs | 4 + .../StringLengthAttributeAdapter.cs | 4 + .../Security/Cryptography/CryptoAlgorithms.cs | 1 + .../System.Web/Security/FormsIdentity.cs | 3 +- .../System.Web/State/SessionStateModule.cs | 15 +- .../System.Web/State/SessionStateUtil.cs | 18 + .../System.Web/TaskAsyncHelper.cs | 7 + .../System.Web/UI/PartialCachingControl.cs | 44 +- .../System.Web/UI/WebControls/Calendar.cs | 2 +- .../UI/WebControls/QueryExtensions.cs | 12 +- .../System.Web/UI/WebControls/xml.cs | 4 + .../referencesource/System.Web/Util/GCUtil.cs | 29 + .../System.Web/Util/StringUtil.cs | 2 + .../System.Web/Util/SynchronizationHelper.cs | 2 +- .../System.Web/Util/XmlUtils.cs | 13 + .../System.Web/XmlSiteMapProvider.cs | 1 + .../AuthoringOM/Compiler/CompileXomlTask.cs | 3 +- .../Design/ComponentSerializationService.cs | 4 +- .../System.Workflow.Runtime/Tracking.cs | 13 +- .../Tracking/TrackingProfileSerializer.cs | 3 +- .../WorkflowRuntime.cs | 11 + .../Clr/inc/AppContextDefaultValues.cs | 11 + .../InternalApis/Clr/inc/LocalAppContext.cs | 10 + .../Core/AppContextDefaultValues.Defaults.cs | 5 + .../Xml/Core/LocalAppContextSwitches.cs | 10 + .../Xml/Serialization/Xmlcustomformatter.cs | 18 +- .../Clr/inc/AppContextDefaultValues.cs | 11 + .../InternalApis/Clr/inc/LocalAppContext.cs | 10 + .../NDP_Common/inc/PinnableBufferCache.cs | 12 +- .../microsoft/win32/UnsafeNativeMethods.cs | 31 +- .../system/componentmodel/MemberDescriptor.cs | 16 +- .../System/Net/Cache/RequestCacheManager.cs | 20 + .../Net/Configuration/DefaultProxySection.cs | 55 +- .../net/System/Net/HttpListenerRequest.cs | 22 +- .../System/net/System/Net/Internal.cs | 21 +- .../net/System/Net/NetworkCredential.cs | 17 +- .../System/Net/SecureProtocols/_SslState.cs | 10 +- .../System/net/System/Net/ServicePoint.cs | 4 + .../net/System/Net/ServicePointManager.cs | 158 +- .../Net/Sockets/Socket.cs.REMOVED.git-id | 2 +- .../Net/UnsafeNativeMethods.cs.REMOVED.git-id | 2 +- .../net/System/Net/WebHeaderCollection.cs | 2 +- .../System/net/System/Net/WebRequest.cs | 54 +- .../System/net/System/Net/_SecureChannel.cs | 19 +- .../System/net/System/Net/_Semaphore.cs | 14 +- .../System/net/System/Net/_TimerThread.cs | 2 + .../System/net/System/Net/webproxy.cs | 30 +- .../System/net/System/UriExt.cs | 5 + .../system/text/regularexpressions/Regex.cs | 8 +- .../io/system/io/FileSystemWatcher.cs | 3 - .../system/diagnosticts/AsyncStreamReader.cs | 52 + .../diagnosticts/Process.cs.REMOVED.git-id | 2 +- .../diagnosticts/ProcessModuleCollection.cs | 264 + .../diagnosticts/ProcessThreadCollection.cs | 246 + .../sys/AppContextDefaultValues.Defaults.cs | 7 +- .../System/sys/LocalAppContextSwitches.cs | 31 +- .../sys/system/IO/ports/InternalResources.cs | 4 + .../System/sys/system/threading/semaphore.cs | 60 + .../markup/ValueSerializerAttribute.cs | 2 + .../Tasks/Xaml/PartialClassGenerationTask.cs | 7 +- .../Build/Tasks/Xaml/XamlBuildTaskServices.cs | 6 + .../NDP_Common/inc/PinnableBufferCache.cs | 12 +- .../win32/win32native.cs.REMOVED.git-id | 2 +- .../mscorlib/system/AppContext/AppContext.cs | 10 +- .../AppContextDefaultValues.Defaults.cs | 17 +- .../AppContext/AppContextDefaultValues.cs | 11 + .../system/AppContext/AppContextSwitches.cs | 42 + .../mscorlib/system/AppDomainSetup.cs | 60 +- .../system/appdomain.cs.REMOVED.git-id | 2 +- .../mscorlib/system/bitconverter.cs | 2 +- .../mscorlib/system/contextboundobject.cs | 2 +- .../mscorlib/system/deployment/cmsutils.cs | 14 +- .../eventing/TraceLogging/SimpleTypeInfos.cs | 9 + .../TraceLogging/TraceLoggingEventSource.cs | 9 +- .../TraceLoggingMetadataCollector.cs | 2 +- .../diagnostics/eventing/activitytracker.cs | 237 +- .../diagnostics/eventing/eventprovider.cs | 2 +- .../eventing/eventsource.cs.REMOVED.git-id | 2 +- .../mscorlib/system/environment.cs | 2 +- .../mscorlib/system/exception.cs | 2 +- .../referencesource/mscorlib/system/gc.cs | 93 + .../system/globalization/compareinfo.cs | 17 +- .../system/globalization/taiwancalendar.cs | 2 +- .../mscorlib/system/io/__error.cs | 20 +- .../mscorlib/system/io/binaryreader.cs | 21 +- .../mscorlib/system/io/binarywriter.cs | 21 +- .../mscorlib/system/io/directory.cs | 139 +- .../mscorlib/system/io/directoryinfo.cs | 16 +- .../mscorlib/system/io/file.cs | 21 +- .../mscorlib/system/io/fileinfo.cs | 12 +- .../system/io/filestream.cs.REMOVED.git-id | 2 +- .../system/io/filesystemenumerable.cs | 19 +- .../mscorlib/system/io/filesysteminfo.cs | 10 +- .../mscorlib/system/io/longpath.cs | 57 +- .../mscorlib/system/io/path.cs | 318 +- .../mscorlib/system/io/stream.cs | 2 +- .../mscorlib/system/io/textreader.cs | 2 +- .../mscorlib/system/io/textwriter.cs | 2 +- .../system/resources/resourcereader.cs | 17 +- .../interopservices/runtimeenvironment.cs | 9 +- .../windowsruntime/nativemethods.cs | 7 + .../formatters/binary/binaryformatter.cs | 2 +- .../security/accesscontrol/filesecurity.cs | 47 +- .../mscorlib/system/security/attributes.cs | 4 +- .../system/security/claims/ClaimsIdentity.cs | 23 +- .../security/cryptography/cryptoconfig.cs | 55 +- .../system/security/cryptography/dsa.cs | 79 + .../cryptography/dsacryptoserviceprovider.cs | 30 + .../cryptography/rc2cryptoserviceprovider.cs | 6 + .../cryptography/rfc2898derivebytes.cs | 6 +- .../cryptography/rsacryptoserviceprovider.cs | 23 +- .../rsaoaepkeyexchangedeformatter.cs | 15 +- .../rsaoaepkeyexchangeformatter.cs | 15 +- .../rsapkcs1keyexchangedeformatter.cs | 15 +- .../rsapkcs1keyexchangeformatter.cs | 15 +- .../rsapkcs1signaturedeformatter.cs | 19 + .../rsapkcs1signatureformatter.cs | 19 + .../cryptography/signaturedescription.cs | 48 +- .../system/security/cryptography/utils.cs | 68 + .../x509certificates/x509utils.cs | 2 +- .../security/permissions/fileiopermission.cs | 580 +- .../security/principal/windowsidentity.cs | 4 + .../security/util/stringexpressionset.cs | 52 +- .../system/security/util/urlstring.cs | 32 +- .../mscorlib/system/sharedstatics.cs | 10 + .../mscorlib/system/text/stringbuilder.cs | 5 +- .../threading/Tasks/Task.cs.REMOVED.git-id | 2 +- .../system/threading/eventwaithandle.cs | 54 +- .../mscorlib/system/threading/thread.cs | 12 +- .../system/threading/threadabortexception.cs | 3 +- mcs/errors/cs0029-37.cs | 24 + mcs/errors/cs0122-39.cs | 15 + mcs/errors/cs0177-15.cs | 21 + mcs/errors/cs0619-59.cs | 18 + mcs/errors/cs1070-3.cs | 11 + mcs/errors/cs1501-19.cs | 26 + mcs/errors/cs1691-2.cs | 4 - mcs/errors/cs1691-3.cs | 4 - mcs/errors/cs1691-4.cs | 4 - mcs/errors/cs1691.cs | 6 - mcs/errors/cs1744-3.cs | 18 + mcs/errors/cs1904.cs | 8 - mcs/ilasm/codegen/TypeDef.cs | 4 +- mcs/ilasm/scanner/InstrToken.cs | 4 + mcs/jay/jay.vcxproj | 19 +- mcs/mcs/Makefile | 4 +- mcs/mcs/assembly.cs | 11 +- mcs/mcs/class.cs.REMOVED.git-id | 2 +- mcs/mcs/constant.cs | 28 +- mcs/mcs/context.cs | 18 + mcs/mcs/cs-tokenizer.cs | 6 + mcs/mcs/decl.cs | 2 +- mcs/mcs/ecore.cs.REMOVED.git-id | 2 +- mcs/mcs/eval.cs | 2 +- mcs/mcs/expression.cs.REMOVED.git-id | 2 +- mcs/mcs/generic.cs | 31 +- mcs/mcs/ikvm.cs | 29 +- mcs/mcs/import.cs | 9 +- mcs/mcs/iterators.cs | 3 +- mcs/mcs/mcs.csproj | 2 +- mcs/mcs/membercache.cs | 42 +- mcs/mcs/method.cs | 2 +- mcs/mcs/property.cs | 5 +- mcs/mcs/reflection.cs | 6 +- mcs/mcs/report.cs | 22 +- mcs/mcs/settings.cs | 14 +- mcs/mcs/statement.cs.REMOVED.git-id | 2 +- mcs/tests/gtest-638.cs | 17 + mcs/tests/gtest-639.cs | 47 + mcs/tests/test-254.cs | 13 +- mcs/tests/test-937.cs | 15 + mcs/tests/test-940.cs | 31 + mcs/tests/test-941.cs | 30 + mcs/tests/test-debug-11-ref.xml | 12 +- mcs/tests/test-debug-21-ref.xml | 3 +- mcs/tests/test-debug-28-ref.xml | 4 +- mcs/tests/test-debug-31-ref.xml | 58 + mcs/tests/test-debug-31.cs | 25 + mcs/tests/test-debug-32-ref.xml | 92 + mcs/tests/test-debug-32.cs | 21 + mcs/tests/test-interpolation-05.cs | 7 + mcs/tests/test-iter-23.cs | 4 +- mcs/tests/test-named-10.cs | 18 + mcs/tests/test-partial-35.cs | 19 + mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id | 2 +- mcs/tools/Makefile | 3 +- mcs/tools/al/Al.cs | 255 +- mcs/tools/btls/AssemblyInfo.cs | 26 + mcs/tools/btls/Makefile | 17 + mcs/tools/btls/btls-cert-sync.cs | 61 + mcs/tools/btls/btls-cert-sync.exe.sources | 4 + .../cil-stringreplacer/cil-stringreplacer.cs | 39 +- .../CommonCryptorGenerator.cs | 13 +- mcs/tools/commoncryptogenerator/generator.cs | 8 +- mcs/tools/compiler-tester/compiler-tester.cs | 12 +- mcs/tools/compiler-tester/xmldocdiff.cs | 6 +- mcs/tools/corcompare/Util.cs | 4 +- mcs/tools/corcompare/mono-api-info.cs | 157 +- mcs/tools/linker/Descriptors/mscorlib.xml | 49 +- .../linker/Mono.Linker.Steps/MarkStep.cs | 24 +- .../linker/Mono.Linker.Steps/OutputStep.cs | 2 +- .../Mono.Linker.Steps/ResolveFromXmlStep.cs | 8 + .../linker/Mono.Linker.Steps/SweepStep.cs | 4 +- .../linker/Mono.Linker.Steps/TypeMapStep.cs | 8 +- .../linker/Mono.Linker/AssemblyResolver.cs | 2 +- mcs/tools/linker/Mono.Linker/LinkContext.cs | 2 +- mcs/tools/mconfig/Makefile | 7 +- mcs/tools/mconfig/mconfig.cs | 2 +- mcs/tools/mdoc/Makefile | 51 +- .../mdoc/Mono.Documentation/exceptions.cs | 5 +- .../monodocer.cs.REMOVED.git-id | 2 +- .../MyFramework.MyNamespace/MyClass.xml | 8 + .../MyClassExtensions.xml | 47 + .../en.expected-dropns-classic-v1/index.xml | 34 + .../MyFramework.MyNamespace/MyClass.xml | 8 + .../MyClassExtensions.xml | 47 + .../MyOtherClass.xml | 15 +- .../index.xml | 34 + .../MyFramework.MyNamespace/MyClass.xml | 18 + .../MyClassExtensions.xml | 47 + .../TypeOnlyInClassic.xml | 5 +- .../Test/en.expected-dropns-delete/index.xml | 34 + .../MyFramework.MyNamespace/MyClass.xml | 16 +- .../MyClassExtensions.xml | 63 + .../index.xml | 24 + .../MyClassExtensions.xml | 63 + .../Test/en.expected-dropns-multi/index.xml | 24 + mcs/tools/mkbundle/Makefile | 15 +- mcs/tools/mkbundle/mkbundle.cs | 453 +- mcs/tools/mono-api-html/ApiDiff.cs | 21 +- mcs/tools/mono-api-html/AssemblyComparer.cs | 8 +- mcs/tools/mono-api-html/ClassComparer.cs | 16 +- mcs/tools/mono-api-html/FieldComparer.cs | 18 +- mcs/tools/mono-api-html/MemberComparer.cs | 42 +- .../mono-symbolicate/LocationProvider.cs | 19 +- mcs/tools/mono-symbolicate/Makefile | 2 +- mcs/tools/mono-symbolicate/SymbolManager.cs | 33 +- mcs/tools/security/cert-sync.cs | 19 +- mcs/tools/tuner/Mono.Tuner/CheckVisibility.cs | 4 +- .../Mono.Tuner/MoonlightA11yProcessor.cs | 4 +- .../tuner/Mono.Tuner/RemoveSerialization.cs | 2 +- mono/Makefile.am | 12 +- mono/Makefile.in | 22 +- mono/arch/Makefile.in | 13 +- mono/arch/amd64/Makefile.in | 13 +- mono/arch/arm/Makefile.in | 13 +- mono/arch/arm/arm-codegen.h | 10 + mono/arch/arm64/Makefile.in | 13 +- mono/arch/ia64/Makefile.in | 13 +- mono/arch/mips/Makefile.in | 13 +- mono/arch/ppc/Makefile.in | 13 +- mono/arch/s390x/Makefile.in | 13 +- mono/arch/sparc/Makefile.in | 13 +- mono/arch/x86/Makefile.in | 13 +- mono/benchmark/Makefile.in | 13 +- mono/btls/Makefile.am | 41 + mono/btls/Makefile.in | 562 ++ mono/cil/Makefile.in | 13 +- mono/cil/cil-opcodes.xml | 1 + mono/cil/opcode.def | 1 + mono/dis/Makefile.in | 13 +- mono/dis/main.c | 11 +- mono/io-layer/Makefile.am | 9 +- mono/io-layer/Makefile.in | 50 +- mono/io-layer/error.c | 2 +- mono/io-layer/event-private.h | 11 +- mono/io-layer/events.c | 753 +-- mono/io-layer/handles-private.h | 367 -- mono/io-layer/handles.c | 1840 ------- mono/io-layer/handles.h | 27 - mono/io-layer/io-private.h | 8 - mono/io-layer/io-trace.h | 1 + mono/io-layer/io.c.REMOVED.git-id | 2 +- mono/io-layer/io.h | 1 + mono/io-layer/locking.c | 6 +- mono/io-layer/mutex-private.h | 13 +- mono/io-layer/mutexes.c | 803 +-- mono/io-layer/mutexes.h | 5 + mono/io-layer/posix.c | 6 +- mono/io-layer/process-private.h | 4 +- mono/io-layer/processes.c | 201 +- mono/io-layer/processes.h | 3 +- mono/io-layer/semaphore-private.h | 11 +- mono/io-layer/semaphores.c | 534 +- mono/io-layer/shared.c | 12 +- mono/io-layer/shared.h | 1 - mono/io-layer/socket-private.h | 5 +- mono/io-layer/sockets.c | 162 +- mono/io-layer/thread-private.h | 35 - mono/io-layer/threads.h | 40 - mono/io-layer/uglify.h | 1 - mono/io-layer/wait.c | 614 +-- mono/io-layer/wait.h | 7 +- mono/io-layer/wapi-private.h | 147 +- mono/io-layer/wapi-remap.h | 5 - mono/io-layer/wapi.c | 187 + mono/io-layer/wapi.h | 18 +- mono/io-layer/wapi_glob.c | 12 +- mono/io-layer/wthreads.c | 451 -- mono/metadata/Makefile.am | 60 +- mono/metadata/Makefile.in.REMOVED.git-id | 2 +- mono/metadata/appdomain.c | 107 +- mono/metadata/assembly.c | 3653 ------------- mono/metadata/assembly.c.REMOVED.git-id | 1 + mono/metadata/assembly.h | 2 +- mono/metadata/attach.c | 11 +- mono/metadata/boehm-gc.c | 43 +- mono/metadata/class-internals.h | 24 +- mono/metadata/class.c.REMOVED.git-id | 2 +- mono/metadata/cominterop.c.REMOVED.git-id | 2 +- mono/metadata/coree.c | 4 +- mono/metadata/custom-attrs-internals.h | 15 + mono/metadata/custom-attrs.c | 1899 +++++++ mono/metadata/debug-helpers.c | 10 +- mono/metadata/domain-internals.h | 15 +- mono/metadata/domain.c | 13 +- mono/metadata/dynamic-image-internals.h | 44 + mono/metadata/dynamic-image.c | 562 ++ mono/metadata/dynamic-stream-internals.h | 30 + mono/metadata/dynamic-stream.c | 131 + mono/metadata/exception-internals.h | 12 +- mono/metadata/exception.c | 170 +- mono/metadata/exception.h | 11 + mono/metadata/file-io.c | 18 +- mono/metadata/file-io.h | 1 + mono/metadata/file-mmap-posix.c | 69 +- mono/metadata/gc-internals.h | 2 - mono/metadata/gc.c | 248 +- mono/metadata/handle.c | 345 +- mono/metadata/handle.h | 377 +- mono/metadata/icall-def.h | 395 +- mono/metadata/icall.c.REMOVED.git-id | 2 +- mono/metadata/image.c | 6 +- mono/metadata/loader.c | 17 +- mono/metadata/loader.h | 7 + mono/metadata/locales.c | 6 +- mono/metadata/lock-tracer.c | 9 +- mono/metadata/marshal.c.REMOVED.git-id | 2 +- mono/metadata/marshal.h | 14 +- mono/metadata/mempool.c | 39 +- mono/metadata/metadata-cross-helpers.c | 1 + mono/metadata/metadata-internals.h | 2 + .../metadata/metadata-verify.c.REMOVED.git-id | 2 +- mono/metadata/metadata.c.REMOVED.git-id | 2 +- mono/metadata/metadata.h | 5 +- mono/metadata/monitor.c | 52 +- mono/metadata/monitor.h | 5 +- mono/metadata/mono-config.c | 2 +- mono/metadata/mono-perfcounters.c | 103 +- mono/metadata/mono-route.c | 4 +- mono/metadata/mono-security.c | 11 +- mono/metadata/null-gc.c | 30 +- mono/metadata/object-internals.h | 151 +- mono/metadata/object-offsets.h | 3 + mono/metadata/object.c.REMOVED.git-id | 2 +- mono/metadata/object.h | 3 + mono/metadata/opcodes.h | 2 +- mono/metadata/process.c | 1 + mono/metadata/profiler.c | 4 +- mono/metadata/reflection-cache.h | 80 + mono/metadata/reflection-internals.h | 16 +- mono/metadata/reflection.c | 2876 ++++++++++ mono/metadata/reflection.c.REMOVED.git-id | 1 - mono/metadata/reflection.h | 1 + mono/metadata/remoting.c | 164 +- mono/metadata/remoting.h | 6 - mono/metadata/sgen-bridge-internals.h | 12 +- mono/metadata/sgen-bridge.c | 50 +- mono/metadata/sgen-bridge.h | 27 +- mono/metadata/sgen-client-mono.h | 6 + mono/metadata/sgen-dynarray.h | 346 ++ mono/metadata/sgen-mono.c | 132 +- mono/metadata/sgen-new-bridge.c | 316 +- mono/metadata/sgen-old-bridge.c | 12 +- mono/metadata/sgen-os-coop.c | 9 +- mono/metadata/sgen-os-posix.c | 1 + mono/metadata/sgen-tarjan-bridge.c | 463 +- mono/metadata/socket-io.c | 144 +- mono/metadata/sre-encode.c | 1303 +++++ mono/metadata/sre-internals.h | 157 + mono/metadata/sre-save.c.REMOVED.git-id | 1 + mono/metadata/sre.c.REMOVED.git-id | 1 + mono/metadata/threadpool-ms-io.c | 2 +- mono/metadata/threadpool-ms.c | 105 +- mono/metadata/threads-types.h | 19 +- mono/metadata/threads.c.REMOVED.git-id | 2 +- mono/metadata/verify.c.REMOVED.git-id | 2 +- mono/metadata/wrapper-types.h | 2 - mono/mini/Makefile.am | 96 +- mono/mini/Makefile.am.in | 96 +- mono/mini/Makefile.in.REMOVED.git-id | 2 +- mono/mini/abcremoval.c | 73 +- mono/mini/abcremoval.h | 12 +- mono/mini/alias-analysis.c | 2 +- mono/mini/aot-compiler.c.REMOVED.git-id | 2 +- mono/mini/aot-runtime.c.REMOVED.git-id | 2 +- mono/mini/aot-tests.cs | 12 +- mono/mini/branch-opts.c | 6 +- mono/mini/cpu-amd64.md | 3 +- mono/mini/debugger-agent.c.REMOVED.git-id | 2 +- mono/mini/driver.c | 69 +- mono/mini/emitnunit.pl | 76 - mono/mini/exceptions-amd64.c | 10 +- mono/mini/exceptions-arm.c | 4 +- mono/mini/exceptions-x86.c | 10 +- mono/mini/generics.cs | 2 +- mono/mini/gshared.cs | 34 + mono/mini/jit-icalls.c | 89 +- mono/mini/linear-scan.c | 8 +- mono/mini/llvm-jit.cpp | 65 +- mono/mini/local-propagation.c | 293 +- mono/mini/main.c | 185 +- mono/mini/method-to-ir.c.REMOVED.git-id | 2 +- mono/mini/mini-amd64-gsharedvt.c | 44 +- mono/mini/mini-amd64-gsharedvt.h | 1 + mono/mini/mini-amd64.c.REMOVED.git-id | 2 +- mono/mini/mini-amd64.h | 28 +- mono/mini/mini-arm.c.REMOVED.git-id | 2 +- mono/mini/mini-arm.h | 2 + mono/mini/mini-arm64.c.REMOVED.git-id | 2 +- mono/mini/mini-arm64.h | 2 - mono/mini/mini-codegen.c | 4 + mono/mini/mini-exceptions.c | 110 +- .../mini-generic-sharing.c.REMOVED.git-id | 2 +- mono/mini/mini-llvm-cpp.cpp | 29 +- mono/mini/mini-llvm-cpp.h | 11 +- mono/mini/mini-llvm.c.REMOVED.git-id | 2 +- mono/mini/mini-native-types.c | 7 + mono/mini/mini-ops.h | 4 + mono/mini/mini-posix.c | 61 +- mono/mini/mini-runtime.c.REMOVED.git-id | 2 +- mono/mini/mini-trampolines.c | 64 +- mono/mini/mini-unwind.h | 2 +- mono/mini/mini-windows-dllmain.c | 40 + mono/mini/mini-x86.c.REMOVED.git-id | 2 +- mono/mini/mini-x86.h | 1 + mono/mini/mini.c.REMOVED.git-id | 2 +- mono/mini/mini.h.REMOVED.git-id | 2 +- mono/mini/patch-info.h | 1 + mono/mini/seq-points.c | 95 +- mono/mini/tasklets.c | 52 + mono/mini/test_op_il_seq_point.sh | 9 +- mono/mini/tramp-amd64-gsharedvt.c | 37 +- mono/mini/tramp-amd64.c | 71 +- mono/mini/tramp-arm.c | 35 +- mono/mini/unwind.c | 6 +- mono/mini/version.h | 2 +- mono/profiler/Makefile.am | 11 +- mono/profiler/Makefile.in | 34 +- mono/profiler/decode.c.REMOVED.git-id | 1 - .../mono-profiler-log.c.REMOVED.git-id | 1 + .../{proflog.h => mono-profiler-log.h} | 3 +- mono/profiler/mono-profiler-vtune.c | 6 +- mono/profiler/mprof-report.c.REMOVED.git-id | 1 + mono/profiler/proflog.c.REMOVED.git-id | 1 - mono/profiler/utils.c | 426 -- mono/profiler/utils.h | 24 - mono/sgen/Makefile.in | 13 +- mono/sgen/sgen-archdep.h | 6 + mono/sgen/sgen-cardtable.c | 4 +- mono/sgen/sgen-copy-object.h | 24 + mono/sgen/sgen-debug.c | 47 +- mono/sgen/sgen-gc.c.REMOVED.git-id | 2 +- mono/sgen/sgen-gc.h | 42 +- mono/sgen/sgen-gray.c | 61 +- mono/sgen/sgen-gray.h | 10 +- mono/sgen/sgen-los.c | 10 +- mono/sgen/sgen-marksweep-drain-gray-stack.h | 2 +- mono/sgen/sgen-marksweep.c | 182 +- mono/sgen/sgen-pinning-stats.c | 26 +- mono/sgen/sgen-protocol-def.h | 7 + mono/sgen/sgen-protocol.c | 18 +- mono/sgen/sgen-protocol.h | 2 +- mono/sgen/sgen-workers.c | 30 +- mono/sgen/sgen-workers.h | 4 +- mono/tests/Makefile.am | 469 +- mono/tests/Makefile.in | 422 +- mono/tests/abort-cctor.cs | 332 ++ mono/tests/appdomain-async-invoke.cs | 49 - mono/tests/appdomain-client.cs | 19 - mono/tests/appdomain-exit.cs | 16 - mono/tests/appdomain-thread-abort.cs | 221 - mono/tests/appdomain-unload-callback.cs | 44 - ...ain-unload-doesnot-raise-pending-events.cs | 29 - mono/tests/appdomain-unload.cs | 293 - mono/tests/appdomain.cs | 36 - mono/tests/appdomain1.cs | 99 - mono/tests/appdomain2.cs | 73 - mono/tests/assembly_append_ordering.cs | 59 - mono/tests/assemblyresolve/Makefile.am | 15 +- mono/tests/assemblyresolve/Makefile.in | 26 +- mono/tests/assemblyresolve_event2.2.cs | 39 - mono/tests/async-exc-compilation.cs | 1 + mono/tests/bug-30085.cs | 2 +- mono/tests/bug-322722_dyn_method_throw.2.cs | 29 - mono/tests/bug-322722_patch_bx.2.cs | 30 - mono/tests/bug-333798-tb.2.cs | 64 - mono/tests/bug-335131.2.cs | 79 - mono/tests/bug-349190.2.cs | 130 - mono/tests/bug-36848.cs | 52 - mono/tests/bug-389886-2.cs | 96 - mono/tests/bug-389886-3.cs | 110 - ...-389886-sre-generic-interface-instances.cs | 116 - mono/tests/bug-461867.cs | 6 + mono/tests/bug-462592.cs | 66 - mono/tests/bug-47295.cs | 85 - mono/tests/bug-48015.cs | 48 - mono/tests/bug-515884.il | 37 - mono/tests/bug-544446.cs | 41 - mono/tests/bug-575941.cs | 58 - mono/tests/bug-80307.cs | 38 - mono/tests/cominterop.cs | 1309 ----- mono/tests/constraints-load.il | 212 - mono/tests/cross-domain.cs | 278 - mono/tests/custom-attr-errors.cs | 12 + mono/tests/delegate9.cs | 43 - mono/tests/dynamic-generic-size.cs | 61 - mono/tests/dynamic-method-access.2.cs | 32 - mono/tests/dynamic-method-finalize.2.cs | 51 - mono/tests/dynamic-method-resurrection.cs | 69 - mono/tests/dynamic-method-stack-traces.cs | 86 - mono/tests/gc-descriptors/Makefile.in | 13 +- mono/tests/gc-graystack-stress.cs | 6 +- mono/tests/generic-marshalbyref.2.cs | 81 - mono/tests/generic-type-builder.2.cs | 90 - mono/tests/generic-unloading.2.cs | 35 - mono/tests/generic-xdomain.2.cs | 54 - mono/tests/generic_type_definition.2.cs | 68 - mono/tests/libtest.c.REMOVED.git-id | 2 +- mono/tests/loader.cs | 46 - mono/tests/marshal-valuetypes.cs | 19 - mono/tests/marshal.cs | 6 + mono/tests/marshal9.cs | 10 +- mono/tests/marshalbool.cs | 50 +- mono/tests/monitor.cs | 77 - mono/tests/pinvoke2.cs | 1901 ------- mono/tests/pinvoke3.cs | 15 + mono/tests/priority.cs | 131 + mono/tests/reference-loader.cs | 110 + mono/tests/remoting1.cs | 213 - mono/tests/remoting2.cs | 113 - mono/tests/remoting3.cs | 123 - mono/tests/remoting5.cs | 100 - mono/tests/stackframes-async.2.cs | 58 - mono/tests/test-runner.cs | 180 +- mono/tests/tests-config.in | 2 + mono/tests/thread6.cs | 253 - mono/tests/threadpool-exceptions7.cs | 31 - mono/tests/transparentproxy.cs | 4866 ----------------- mono/tests/unload-appdomain-on-shutdown.cs | 39 - mono/tests/winx64structs.cs | 10 + mono/tests/xdomain-threads.cs | 74 - mono/unit-tests/Makefile.in | 13 +- mono/unit-tests/test-conc-hashtable.c | 4 + mono/unit-tests/test-mono-handle.c | 24 +- mono/utils/Makefile.am | 10 +- mono/utils/Makefile.in | 106 +- mono/utils/checked-build.c | 2 +- mono/utils/dlmalloc.c.REMOVED.git-id | 2 +- mono/utils/lock-free-alloc.c | 2 +- mono/utils/lock-free-alloc.h | 4 +- mono/utils/mono-codeman.c | 6 +- mono/utils/mono-compiler.h | 6 - mono/utils/mono-context.h | 14 +- mono/utils/mono-coop-mutex.h | 42 +- mono/utils/mono-coop-semaphore.h | 16 +- mono/utils/mono-counters.c | 6 +- mono/utils/mono-dl.c | 12 +- mono/utils/mono-error-internals.h | 7 +- mono/utils/mono-error.c | 35 +- mono/utils/mono-error.h | 2 + mono/utils/mono-log-android.c | 92 + mono/utils/mono-log-common.c | 152 + mono/utils/mono-log-darwin.c | 47 + mono/utils/mono-log-posix.c | 101 + mono/utils/mono-log-windows.c | 124 + mono/utils/mono-logger-internals.h | 42 +- mono/utils/mono-logger.c | 236 +- mono/utils/mono-logger.h | 3 +- mono/utils/mono-mmap.c | 4 +- mono/utils/mono-os-mutex.h | 171 +- mono/utils/mono-os-semaphore.h | 190 +- mono/utils/mono-proclib.c | 24 +- mono/utils/mono-publib.c | 18 + mono/utils/mono-publib.h | 25 + mono/utils/mono-rand.c | 22 +- mono/utils/mono-threads-android.c | 2 +- mono/utils/mono-threads-coop.c | 16 +- mono/utils/mono-threads-freebsd.c | 2 +- mono/utils/mono-threads-linux.c | 2 +- mono/utils/mono-threads-mach-abort-syscall.c | 12 +- mono/utils/mono-threads-mach.c | 20 +- mono/utils/mono-threads-netbsd.c | 23 + mono/utils/mono-threads-openbsd.c | 2 +- mono/utils/mono-threads-posix-abort-syscall.c | 6 +- mono/utils/mono-threads-posix.c | 350 +- .../mono-threads-windows-abort-syscall.c | 6 +- mono/utils/mono-threads-windows.c | 208 +- mono/utils/mono-threads.c | 217 +- mono/utils/mono-threads.h | 119 +- mono/utils/mono-uri.c | 2 +- mono/utils/w32handle.c | 1518 +++++ mono/utils/w32handle.h | 183 + msvc/Makefile.in | 13 +- msvc/build-all.vcxproj | 155 + msvc/build-init.vcxproj | 148 + msvc/build-install.vcxproj | 151 + msvc/build-package.vcxproj | 151 + msvc/create-windef.pl | 2 +- msvc/eglib.vcxproj | 203 +- msvc/genmdesc.vcxproj | 378 +- msvc/libgc.vcxproj | 200 +- msvc/libgcmonosgen.vcxproj | 223 + msvc/libmono-static.vcxproj | 339 ++ msvc/libmono.vcxproj | 597 +- msvc/libmonoruntime.vcxproj | 282 +- msvc/libmonoutils.vcxproj | 140 +- msvc/libtest.vcxproj | 78 +- msvc/mono-full-aot-compile-test.vcxproj | 203 + msvc/mono-full-aot-run-test.vcxproj | 203 + msvc/mono-mini-regression-test.vcxproj | 204 + msvc/mono-nunit-test.vcxproj | 224 + msvc/mono-testdriver-test.vcxproj | 220 + msvc/mono.def | 17 +- msvc/mono.props | 109 +- msvc/mono.sln | 368 +- msvc/mono.vcxproj | 267 +- msvc/monodis.vcxproj | 101 +- msvc/monograph.vcxproj | 87 +- msvc/monoposixhelper.vcxproj | 81 +- msvc/pedump.vcxproj | 125 +- msvc/profiler-vtune.vcxproj | 127 +- msvc/test-invoke.vcxproj | 95 +- msvc/test-metadata.vcxproj | 95 +- msvc/test_eglib.vcxproj | 83 +- msvc/teste.vcxproj | 95 +- msvc/winsetup.bat | 72 +- po/Makefile.in | 13 +- po/mcs/de.gmo | Bin 5406 -> 5406 bytes po/mcs/de.po.REMOVED.git-id | 2 +- po/mcs/es.gmo | Bin 16329 -> 16329 bytes po/mcs/es.po.REMOVED.git-id | 2 +- po/mcs/ja.gmo | Bin 20863 -> 20863 bytes po/mcs/ja.po.REMOVED.git-id | 2 +- po/mcs/mcs.pot | 628 +-- po/mcs/pt_BR.gmo | Bin 73161 -> 73161 bytes po/mcs/pt_BR.po.REMOVED.git-id | 2 +- runtime/Makefile.am | 23 +- runtime/Makefile.in | 33 +- samples/Makefile.in | 13 +- samples/embed/teste.c | 14 + scripts/Makefile.am | 6 +- scripts/Makefile.in | 18 +- scripts/submodules/versions.mk | 2 +- support/Makefile.in | 13 +- support/map.c.REMOVED.git-id | 2 +- support/sys-mman.c | 12 + support/zlib-helper.c | 13 +- tools/Makefile.am | 2 +- tools/Makefile.in | 15 +- tools/locale-builder/Makefile.in | 13 +- tools/monograph/Makefile.am | 8 +- tools/monograph/Makefile.in | 47 +- tools/pedump/Makefile.am | 31 + tools/pedump/Makefile.in | 739 +++ {mono/metadata => tools/pedump}/pedump.c | 8 +- tools/sgen/Makefile.am | 9 +- tools/sgen/Makefile.in | 22 +- tools/sgen/sgen-entry-stream.h | 20 + tools/sgen/sgen-grep-binprot.h | 12 + 4912 files changed, 390737 insertions(+), 49310 deletions(-) create mode 100644 acceptance-tests/profiler-stress.mk delete mode 100644 eglib/src/vasprintf.c delete mode 100644 eglib/src/vasprintf.h create mode 100644 external/boringssl/.clang-format create mode 100644 external/boringssl/.github/PULL_REQUEST_TEMPLATE create mode 100644 external/boringssl/.gitignore create mode 100644 external/boringssl/BUILDING.md create mode 100644 external/boringssl/CMakeLists.txt create mode 100644 external/boringssl/CONTRIBUTING.md create mode 100644 external/boringssl/FUZZING.md create mode 100644 external/boringssl/INCORPORATING.md create mode 100644 external/boringssl/LICENSE create mode 100644 external/boringssl/PORTING.md create mode 100644 external/boringssl/README.md create mode 100644 external/boringssl/STYLE.md create mode 100644 external/boringssl/codereview.settings create mode 100644 external/boringssl/crypto/CMakeLists.txt create mode 100644 external/boringssl/crypto/aes/CMakeLists.txt create mode 100644 external/boringssl/crypto/aes/aes.c create mode 100644 external/boringssl/crypto/aes/aes_test.cc create mode 100644 external/boringssl/crypto/aes/asm/aes-586.pl.REMOVED.git-id create mode 100644 external/boringssl/crypto/aes/asm/aes-armv4.pl create mode 100644 external/boringssl/crypto/aes/asm/aes-x86_64.pl create mode 100644 external/boringssl/crypto/aes/asm/aesni-x86.pl create mode 100644 external/boringssl/crypto/aes/asm/aesni-x86_64.pl.REMOVED.git-id create mode 100644 external/boringssl/crypto/aes/asm/aesv8-armx.pl create mode 100644 external/boringssl/crypto/aes/asm/bsaes-armv7.pl create mode 100644 external/boringssl/crypto/aes/asm/bsaes-x86_64.pl create mode 100644 external/boringssl/crypto/aes/asm/vpaes-x86.pl create mode 100644 external/boringssl/crypto/aes/asm/vpaes-x86_64.pl create mode 100644 external/boringssl/crypto/aes/internal.h create mode 100644 external/boringssl/crypto/aes/mode_wrappers.c create mode 100644 external/boringssl/crypto/asn1/CMakeLists.txt create mode 100644 external/boringssl/crypto/asn1/a_bitstr.c create mode 100644 external/boringssl/crypto/asn1/a_bool.c create mode 100644 external/boringssl/crypto/asn1/a_bytes.c create mode 100644 external/boringssl/crypto/asn1/a_d2i_fp.c create mode 100644 external/boringssl/crypto/asn1/a_dup.c create mode 100644 external/boringssl/crypto/asn1/a_enum.c create mode 100644 external/boringssl/crypto/asn1/a_gentm.c create mode 100644 external/boringssl/crypto/asn1/a_i2d_fp.c create mode 100644 external/boringssl/crypto/asn1/a_int.c create mode 100644 external/boringssl/crypto/asn1/a_mbstr.c create mode 100644 external/boringssl/crypto/asn1/a_object.c create mode 100644 external/boringssl/crypto/asn1/a_octet.c create mode 100644 external/boringssl/crypto/asn1/a_print.c create mode 100644 external/boringssl/crypto/asn1/a_strnid.c create mode 100644 external/boringssl/crypto/asn1/a_time.c create mode 100644 external/boringssl/crypto/asn1/a_type.c create mode 100644 external/boringssl/crypto/asn1/a_utctm.c create mode 100644 external/boringssl/crypto/asn1/a_utf8.c create mode 100644 external/boringssl/crypto/asn1/asn1_lib.c create mode 100644 external/boringssl/crypto/asn1/asn1_locl.h create mode 100644 external/boringssl/crypto/asn1/asn1_par.c create mode 100644 external/boringssl/crypto/asn1/asn1_test.cc create mode 100644 external/boringssl/crypto/asn1/asn_pack.c create mode 100644 external/boringssl/crypto/asn1/charmap.pl create mode 100644 external/boringssl/crypto/asn1/f_enum.c create mode 100644 external/boringssl/crypto/asn1/f_int.c create mode 100644 external/boringssl/crypto/asn1/f_string.c create mode 100644 external/boringssl/crypto/asn1/t_bitst.c create mode 100644 external/boringssl/crypto/asn1/tasn_dec.c create mode 100644 external/boringssl/crypto/asn1/tasn_enc.c create mode 100644 external/boringssl/crypto/asn1/tasn_fre.c create mode 100644 external/boringssl/crypto/asn1/tasn_new.c create mode 100644 external/boringssl/crypto/asn1/tasn_typ.c create mode 100644 external/boringssl/crypto/asn1/tasn_utl.c create mode 100644 external/boringssl/crypto/asn1/x_bignum.c create mode 100644 external/boringssl/crypto/asn1/x_long.c create mode 100644 external/boringssl/crypto/base64/CMakeLists.txt create mode 100644 external/boringssl/crypto/base64/base64.c create mode 100644 external/boringssl/crypto/base64/base64_test.cc create mode 100644 external/boringssl/crypto/bio/CMakeLists.txt create mode 100644 external/boringssl/crypto/bio/bio.c create mode 100644 external/boringssl/crypto/bio/bio_mem.c create mode 100644 external/boringssl/crypto/bio/bio_test.cc create mode 100644 external/boringssl/crypto/bio/buffer.c create mode 100644 external/boringssl/crypto/bio/connect.c create mode 100644 external/boringssl/crypto/bio/fd.c create mode 100644 external/boringssl/crypto/bio/file.c create mode 100644 external/boringssl/crypto/bio/hexdump.c create mode 100644 external/boringssl/crypto/bio/internal.h create mode 100644 external/boringssl/crypto/bio/pair.c create mode 100644 external/boringssl/crypto/bio/printf.c create mode 100644 external/boringssl/crypto/bio/socket.c create mode 100644 external/boringssl/crypto/bio/socket_helper.c create mode 100644 external/boringssl/crypto/bn/CMakeLists.txt create mode 100644 external/boringssl/crypto/bn/add.c create mode 100644 external/boringssl/crypto/bn/asm/armv4-mont.pl create mode 100644 external/boringssl/crypto/bn/asm/armv8-mont.pl create mode 100644 external/boringssl/crypto/bn/asm/bn-586.pl create mode 100644 external/boringssl/crypto/bn/asm/co-586.pl create mode 100755 external/boringssl/crypto/bn/asm/rsaz-avx2.pl create mode 100755 external/boringssl/crypto/bn/asm/rsaz-x86_64.pl create mode 100644 external/boringssl/crypto/bn/asm/x86-mont.pl create mode 100644 external/boringssl/crypto/bn/asm/x86_64-gcc.c create mode 100755 external/boringssl/crypto/bn/asm/x86_64-mont.pl create mode 100755 external/boringssl/crypto/bn/asm/x86_64-mont5.pl create mode 100644 external/boringssl/crypto/bn/bn.c create mode 100644 external/boringssl/crypto/bn/bn_asn1.c create mode 100644 external/boringssl/crypto/bn/bn_test.cc create mode 100644 external/boringssl/crypto/bn/cmp.c create mode 100644 external/boringssl/crypto/bn/convert.c create mode 100644 external/boringssl/crypto/bn/ctx.c create mode 100644 external/boringssl/crypto/bn/div.c create mode 100644 external/boringssl/crypto/bn/exponentiation.c create mode 100644 external/boringssl/crypto/bn/gcd.c create mode 100644 external/boringssl/crypto/bn/generic.c create mode 100644 external/boringssl/crypto/bn/internal.h create mode 100644 external/boringssl/crypto/bn/kronecker.c create mode 100644 external/boringssl/crypto/bn/montgomery.c create mode 100644 external/boringssl/crypto/bn/mul.c create mode 100644 external/boringssl/crypto/bn/prime.c create mode 100644 external/boringssl/crypto/bn/random.c create mode 100644 external/boringssl/crypto/bn/rsaz_exp.c create mode 100644 external/boringssl/crypto/bn/rsaz_exp.h create mode 100644 external/boringssl/crypto/bn/shift.c create mode 100644 external/boringssl/crypto/bn/sqrt.c create mode 100644 external/boringssl/crypto/buf/CMakeLists.txt create mode 100644 external/boringssl/crypto/buf/buf.c create mode 100644 external/boringssl/crypto/bytestring/CMakeLists.txt create mode 100644 external/boringssl/crypto/bytestring/asn1_compat.c create mode 100644 external/boringssl/crypto/bytestring/ber.c create mode 100644 external/boringssl/crypto/bytestring/bytestring_test.cc create mode 100644 external/boringssl/crypto/bytestring/cbb.c create mode 100644 external/boringssl/crypto/bytestring/cbs.c create mode 100644 external/boringssl/crypto/bytestring/internal.h create mode 100644 external/boringssl/crypto/chacha/CMakeLists.txt create mode 100755 external/boringssl/crypto/chacha/asm/chacha-armv4.pl create mode 100755 external/boringssl/crypto/chacha/asm/chacha-armv8.pl create mode 100755 external/boringssl/crypto/chacha/asm/chacha-x86.pl create mode 100755 external/boringssl/crypto/chacha/asm/chacha-x86_64.pl create mode 100644 external/boringssl/crypto/chacha/chacha.c create mode 100644 external/boringssl/crypto/chacha/chacha_test.cc create mode 100644 external/boringssl/crypto/cipher/CMakeLists.txt create mode 100644 external/boringssl/crypto/cipher/aead.c create mode 100644 external/boringssl/crypto/cipher/aead_test.cc create mode 100644 external/boringssl/crypto/cipher/cipher.c create mode 100644 external/boringssl/crypto/cipher/cipher_test.cc create mode 100644 external/boringssl/crypto/cipher/derive_key.c create mode 100644 external/boringssl/crypto/cipher/e_aes.c create mode 100644 external/boringssl/crypto/cipher/e_chacha20poly1305.c create mode 100644 external/boringssl/crypto/cipher/e_des.c create mode 100644 external/boringssl/crypto/cipher/e_null.c create mode 100644 external/boringssl/crypto/cipher/e_rc2.c create mode 100644 external/boringssl/crypto/cipher/e_rc4.c create mode 100644 external/boringssl/crypto/cipher/e_ssl3.c create mode 100644 external/boringssl/crypto/cipher/e_tls.c create mode 100644 external/boringssl/crypto/cipher/internal.h create mode 100644 external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt create mode 100644 external/boringssl/crypto/cipher/test/aes_128_gcm_tests.txt create mode 100644 external/boringssl/crypto/cipher/test/aes_128_key_wrap_tests.txt create mode 100644 external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt create mode 100644 external/boringssl/crypto/cipher/test/aes_256_gcm_tests.txt create mode 100644 external/boringssl/crypto/cipher/test/aes_256_key_wrap_tests.txt create mode 100644 external/boringssl/crypto/cipher/test/chacha20_poly1305_old_tests.txt create mode 100644 external/boringssl/crypto/cipher/test/chacha20_poly1305_tests.txt create mode 100644 external/boringssl/crypto/cipher/test/cipher_tests.txt create mode 100644 external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id create mode 100755 external/boringssl/crypto/cipher/test/make_all_legacy_aead_tests.sh create mode 100644 external/boringssl/crypto/cipher/test/make_legacy_aead_tests.go create mode 100644 external/boringssl/crypto/cipher/test/rc4_md5_ssl3_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/rc4_md5_tls_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/rc4_sha1_ssl3_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/test/rc4_sha1_tls_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/cipher/tls_cbc.c create mode 100644 external/boringssl/crypto/cmac/CMakeLists.txt create mode 100644 external/boringssl/crypto/cmac/cmac.c create mode 100644 external/boringssl/crypto/cmac/cmac_test.cc create mode 100644 external/boringssl/crypto/conf/CMakeLists.txt create mode 100644 external/boringssl/crypto/conf/conf.c create mode 100644 external/boringssl/crypto/conf/conf_def.h create mode 100644 external/boringssl/crypto/conf/internal.h create mode 100644 external/boringssl/crypto/constant_time_test.c create mode 100644 external/boringssl/crypto/cpu-aarch64-linux.c create mode 100644 external/boringssl/crypto/cpu-arm-linux.c create mode 100644 external/boringssl/crypto/cpu-arm.c create mode 100644 external/boringssl/crypto/cpu-intel.c create mode 100644 external/boringssl/crypto/crypto.c create mode 100644 external/boringssl/crypto/curve25519/CMakeLists.txt create mode 100644 external/boringssl/crypto/curve25519/asm/x25519-asm-arm.S create mode 100644 external/boringssl/crypto/curve25519/asm/x25519-asm-x86_64.S create mode 100644 external/boringssl/crypto/curve25519/curve25519.c.REMOVED.git-id create mode 100644 external/boringssl/crypto/curve25519/ed25519_test.cc create mode 100644 external/boringssl/crypto/curve25519/ed25519_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/curve25519/internal.h create mode 100644 external/boringssl/crypto/curve25519/spake25519.c create mode 100644 external/boringssl/crypto/curve25519/spake25519_test.cc create mode 100644 external/boringssl/crypto/curve25519/x25519-x86_64.c create mode 100644 external/boringssl/crypto/curve25519/x25519_test.cc create mode 100644 external/boringssl/crypto/des/CMakeLists.txt create mode 100644 external/boringssl/crypto/des/des.c create mode 100644 external/boringssl/crypto/des/internal.h create mode 100644 external/boringssl/crypto/dh/CMakeLists.txt create mode 100644 external/boringssl/crypto/dh/check.c create mode 100644 external/boringssl/crypto/dh/dh.c create mode 100644 external/boringssl/crypto/dh/dh_asn1.c create mode 100644 external/boringssl/crypto/dh/dh_test.cc create mode 100644 external/boringssl/crypto/dh/internal.h create mode 100644 external/boringssl/crypto/dh/params.c create mode 100644 external/boringssl/crypto/digest/CMakeLists.txt create mode 100644 external/boringssl/crypto/digest/digest.c create mode 100644 external/boringssl/crypto/digest/digest_test.cc create mode 100644 external/boringssl/crypto/digest/digests.c create mode 100644 external/boringssl/crypto/digest/internal.h create mode 100644 external/boringssl/crypto/digest/md32_common.h create mode 100644 external/boringssl/crypto/dsa/CMakeLists.txt create mode 100644 external/boringssl/crypto/dsa/dsa.c create mode 100644 external/boringssl/crypto/dsa/dsa_asn1.c create mode 100644 external/boringssl/crypto/dsa/dsa_test.c create mode 100644 external/boringssl/crypto/ec/CMakeLists.txt create mode 100755 external/boringssl/crypto/ec/asm/p256-x86_64-asm.pl create mode 100644 external/boringssl/crypto/ec/ec.c create mode 100644 external/boringssl/crypto/ec/ec_asn1.c create mode 100644 external/boringssl/crypto/ec/ec_key.c create mode 100644 external/boringssl/crypto/ec/ec_montgomery.c create mode 100644 external/boringssl/crypto/ec/ec_test.cc create mode 100644 external/boringssl/crypto/ec/example_mul.c create mode 100644 external/boringssl/crypto/ec/internal.h create mode 100644 external/boringssl/crypto/ec/oct.c create mode 100644 external/boringssl/crypto/ec/p224-64.c create mode 100644 external/boringssl/crypto/ec/p256-64.c create mode 100644 external/boringssl/crypto/ec/p256-x86_64-table.h.REMOVED.git-id create mode 100644 external/boringssl/crypto/ec/p256-x86_64.c create mode 100644 external/boringssl/crypto/ec/simple.c create mode 100644 external/boringssl/crypto/ec/util-64.c create mode 100644 external/boringssl/crypto/ec/wnaf.c create mode 100644 external/boringssl/crypto/ecdh/CMakeLists.txt create mode 100644 external/boringssl/crypto/ecdh/ecdh.c create mode 100644 external/boringssl/crypto/ecdsa/CMakeLists.txt create mode 100644 external/boringssl/crypto/ecdsa/ecdsa.c create mode 100644 external/boringssl/crypto/ecdsa/ecdsa_asn1.c create mode 100644 external/boringssl/crypto/ecdsa/ecdsa_test.cc create mode 100644 external/boringssl/crypto/engine/CMakeLists.txt create mode 100644 external/boringssl/crypto/engine/engine.c create mode 100644 external/boringssl/crypto/err/CMakeLists.txt create mode 100644 external/boringssl/crypto/err/asn1.errordata create mode 100644 external/boringssl/crypto/err/bio.errordata create mode 100644 external/boringssl/crypto/err/bn.errordata create mode 100644 external/boringssl/crypto/err/cipher.errordata create mode 100644 external/boringssl/crypto/err/conf.errordata create mode 100644 external/boringssl/crypto/err/dh.errordata create mode 100644 external/boringssl/crypto/err/digest.errordata create mode 100644 external/boringssl/crypto/err/dsa.errordata create mode 100644 external/boringssl/crypto/err/ec.errordata create mode 100644 external/boringssl/crypto/err/ecdh.errordata create mode 100644 external/boringssl/crypto/err/ecdsa.errordata create mode 100644 external/boringssl/crypto/err/engine.errordata create mode 100644 external/boringssl/crypto/err/err.c create mode 100644 external/boringssl/crypto/err/err_data.c create mode 100644 external/boringssl/crypto/err/err_data_generate.go create mode 100644 external/boringssl/crypto/err/err_test.cc create mode 100644 external/boringssl/crypto/err/evp.errordata create mode 100644 external/boringssl/crypto/err/hkdf.errordata create mode 100644 external/boringssl/crypto/err/obj.errordata create mode 100644 external/boringssl/crypto/err/pem.errordata create mode 100644 external/boringssl/crypto/err/pkcs8.errordata create mode 100644 external/boringssl/crypto/err/rsa.errordata create mode 100644 external/boringssl/crypto/err/ssl.errordata create mode 100644 external/boringssl/crypto/err/x509.errordata create mode 100644 external/boringssl/crypto/err/x509v3.errordata create mode 100644 external/boringssl/crypto/evp/CMakeLists.txt create mode 100644 external/boringssl/crypto/evp/digestsign.c create mode 100644 external/boringssl/crypto/evp/evp.c create mode 100644 external/boringssl/crypto/evp/evp_asn1.c create mode 100644 external/boringssl/crypto/evp/evp_ctx.c create mode 100644 external/boringssl/crypto/evp/evp_extra_test.cc create mode 100644 external/boringssl/crypto/evp/evp_test.cc create mode 100644 external/boringssl/crypto/evp/evp_tests.txt create mode 100644 external/boringssl/crypto/evp/internal.h create mode 100644 external/boringssl/crypto/evp/p_dsa_asn1.c create mode 100644 external/boringssl/crypto/evp/p_ec.c create mode 100644 external/boringssl/crypto/evp/p_ec_asn1.c create mode 100644 external/boringssl/crypto/evp/p_rsa.c create mode 100644 external/boringssl/crypto/evp/p_rsa_asn1.c create mode 100644 external/boringssl/crypto/evp/pbkdf.c create mode 100644 external/boringssl/crypto/evp/pbkdf_test.cc create mode 100644 external/boringssl/crypto/evp/print.c create mode 100644 external/boringssl/crypto/evp/sign.c create mode 100644 external/boringssl/crypto/ex_data.c create mode 100644 external/boringssl/crypto/hkdf/CMakeLists.txt create mode 100644 external/boringssl/crypto/hkdf/hkdf.c create mode 100644 external/boringssl/crypto/hkdf/hkdf_test.c create mode 100644 external/boringssl/crypto/hmac/CMakeLists.txt create mode 100644 external/boringssl/crypto/hmac/hmac.c create mode 100644 external/boringssl/crypto/hmac/hmac_test.cc create mode 100644 external/boringssl/crypto/hmac/hmac_tests.txt create mode 100644 external/boringssl/crypto/internal.h create mode 100644 external/boringssl/crypto/lhash/CMakeLists.txt create mode 100644 external/boringssl/crypto/lhash/lhash.c create mode 100644 external/boringssl/crypto/lhash/lhash_test.c create mode 100644 external/boringssl/crypto/lhash/make_macros.sh create mode 100644 external/boringssl/crypto/md4/CMakeLists.txt create mode 100644 external/boringssl/crypto/md4/md4.c create mode 100644 external/boringssl/crypto/md5/CMakeLists.txt create mode 100644 external/boringssl/crypto/md5/asm/md5-586.pl create mode 100644 external/boringssl/crypto/md5/asm/md5-x86_64.pl create mode 100644 external/boringssl/crypto/md5/md5.c create mode 100644 external/boringssl/crypto/mem.c create mode 100644 external/boringssl/crypto/modes/CMakeLists.txt create mode 100644 external/boringssl/crypto/modes/asm/aesni-gcm-x86_64.pl create mode 100644 external/boringssl/crypto/modes/asm/ghash-armv4.pl create mode 100644 external/boringssl/crypto/modes/asm/ghash-x86.pl create mode 100644 external/boringssl/crypto/modes/asm/ghash-x86_64.pl create mode 100644 external/boringssl/crypto/modes/asm/ghashv8-armx.pl create mode 100644 external/boringssl/crypto/modes/cbc.c create mode 100644 external/boringssl/crypto/modes/cfb.c create mode 100644 external/boringssl/crypto/modes/ctr.c create mode 100644 external/boringssl/crypto/modes/gcm.c create mode 100644 external/boringssl/crypto/modes/gcm_test.c create mode 100644 external/boringssl/crypto/modes/internal.h create mode 100644 external/boringssl/crypto/modes/ofb.c create mode 100644 external/boringssl/crypto/newhope/CMakeLists.txt create mode 100644 external/boringssl/crypto/newhope/error_correction.c create mode 100644 external/boringssl/crypto/newhope/internal.h create mode 100644 external/boringssl/crypto/newhope/newhope.c create mode 100644 external/boringssl/crypto/newhope/newhope_statistical_test.cc create mode 100644 external/boringssl/crypto/newhope/newhope_test.cc create mode 100644 external/boringssl/crypto/newhope/newhope_tests.txt.REMOVED.git-id create mode 100644 external/boringssl/crypto/newhope/newhope_vectors_test.cc create mode 100644 external/boringssl/crypto/newhope/ntt.c create mode 100644 external/boringssl/crypto/newhope/poly.c create mode 100644 external/boringssl/crypto/newhope/precomp.c create mode 100644 external/boringssl/crypto/newhope/reduce.c create mode 100644 external/boringssl/crypto/obj/CMakeLists.txt create mode 100644 external/boringssl/crypto/obj/README create mode 100644 external/boringssl/crypto/obj/obj.c create mode 100644 external/boringssl/crypto/obj/obj_dat.h.REMOVED.git-id create mode 100644 external/boringssl/crypto/obj/obj_dat.pl create mode 100644 external/boringssl/crypto/obj/obj_mac.num create mode 100644 external/boringssl/crypto/obj/obj_test.cc create mode 100644 external/boringssl/crypto/obj/obj_xref.c create mode 100644 external/boringssl/crypto/obj/obj_xref.h create mode 100644 external/boringssl/crypto/obj/obj_xref.pl create mode 100644 external/boringssl/crypto/obj/obj_xref.txt create mode 100644 external/boringssl/crypto/obj/objects.pl create mode 100644 external/boringssl/crypto/obj/objects.txt create mode 100644 external/boringssl/crypto/pem/CMakeLists.txt create mode 100644 external/boringssl/crypto/pem/pem_all.c create mode 100644 external/boringssl/crypto/pem/pem_info.c create mode 100644 external/boringssl/crypto/pem/pem_lib.c create mode 100644 external/boringssl/crypto/pem/pem_oth.c create mode 100644 external/boringssl/crypto/pem/pem_pk8.c create mode 100644 external/boringssl/crypto/pem/pem_pkey.c create mode 100644 external/boringssl/crypto/pem/pem_x509.c create mode 100644 external/boringssl/crypto/pem/pem_xaux.c create mode 100755 external/boringssl/crypto/perlasm/arm-xlate.pl create mode 100644 external/boringssl/crypto/perlasm/cbc.pl create mode 100644 external/boringssl/crypto/perlasm/readme create mode 100755 external/boringssl/crypto/perlasm/x86_64-xlate.pl create mode 100644 external/boringssl/crypto/perlasm/x86asm.pl create mode 100644 external/boringssl/crypto/perlasm/x86gas.pl create mode 100644 external/boringssl/crypto/perlasm/x86masm.pl create mode 100644 external/boringssl/crypto/perlasm/x86nasm.pl create mode 100644 external/boringssl/crypto/pkcs8/CMakeLists.txt create mode 100644 external/boringssl/crypto/pkcs8/internal.h create mode 100644 external/boringssl/crypto/pkcs8/p5_pbe.c create mode 100644 external/boringssl/crypto/pkcs8/p5_pbev2.c create mode 100644 external/boringssl/crypto/pkcs8/p8_pkey.c create mode 100644 external/boringssl/crypto/pkcs8/pkcs12_test.cc create mode 100644 external/boringssl/crypto/pkcs8/pkcs8.c create mode 100644 external/boringssl/crypto/pkcs8/pkcs8_test.cc create mode 100644 external/boringssl/crypto/poly1305/CMakeLists.txt create mode 100755 external/boringssl/crypto/poly1305/asm/poly1305-armv4.pl create mode 100755 external/boringssl/crypto/poly1305/asm/poly1305-armv8.pl create mode 100755 external/boringssl/crypto/poly1305/asm/poly1305-x86.pl create mode 100755 external/boringssl/crypto/poly1305/asm/poly1305-x86_64.pl create mode 100644 external/boringssl/crypto/poly1305/internal.h create mode 100644 external/boringssl/crypto/poly1305/poly1305.c create mode 100644 external/boringssl/crypto/poly1305/poly1305_arm.c create mode 100644 external/boringssl/crypto/poly1305/poly1305_arm_asm.S create mode 100644 external/boringssl/crypto/poly1305/poly1305_test.cc create mode 100644 external/boringssl/crypto/poly1305/poly1305_tests.txt create mode 100644 external/boringssl/crypto/poly1305/poly1305_vec.c create mode 100644 external/boringssl/crypto/rand/CMakeLists.txt create mode 100644 external/boringssl/crypto/rand/asm/rdrand-x86_64.pl create mode 100644 external/boringssl/crypto/rand/deterministic.c create mode 100644 external/boringssl/crypto/rand/internal.h create mode 100644 external/boringssl/crypto/rand/rand.c create mode 100644 external/boringssl/crypto/rand/urandom.c create mode 100644 external/boringssl/crypto/rand/windows.c create mode 100644 external/boringssl/crypto/rc4/CMakeLists.txt create mode 100644 external/boringssl/crypto/rc4/asm/rc4-586.pl create mode 100644 external/boringssl/crypto/rc4/asm/rc4-x86_64.pl create mode 100644 external/boringssl/crypto/rc4/rc4.c create mode 100644 external/boringssl/crypto/refcount_c11.c create mode 100644 external/boringssl/crypto/refcount_lock.c create mode 100644 external/boringssl/crypto/refcount_test.c create mode 100644 external/boringssl/crypto/rsa/CMakeLists.txt create mode 100644 external/boringssl/crypto/rsa/blinding.c create mode 100644 external/boringssl/crypto/rsa/internal.h create mode 100644 external/boringssl/crypto/rsa/padding.c create mode 100644 external/boringssl/crypto/rsa/rsa.c create mode 100644 external/boringssl/crypto/rsa/rsa_asn1.c create mode 100644 external/boringssl/crypto/rsa/rsa_impl.c create mode 100644 external/boringssl/crypto/rsa/rsa_test.cc create mode 100644 external/boringssl/crypto/sha/CMakeLists.txt create mode 100644 external/boringssl/crypto/sha/asm/sha1-586.pl create mode 100644 external/boringssl/crypto/sha/asm/sha1-armv4-large.pl create mode 100644 external/boringssl/crypto/sha/asm/sha1-armv8.pl create mode 100644 external/boringssl/crypto/sha/asm/sha1-x86_64.pl create mode 100644 external/boringssl/crypto/sha/asm/sha256-586.pl create mode 100644 external/boringssl/crypto/sha/asm/sha256-armv4.pl create mode 100644 external/boringssl/crypto/sha/asm/sha512-586.pl create mode 100644 external/boringssl/crypto/sha/asm/sha512-armv4.pl create mode 100644 external/boringssl/crypto/sha/asm/sha512-armv8.pl create mode 100644 external/boringssl/crypto/sha/asm/sha512-x86_64.pl create mode 100644 external/boringssl/crypto/sha/sha1.c create mode 100644 external/boringssl/crypto/sha/sha256.c create mode 100644 external/boringssl/crypto/sha/sha512.c create mode 100644 external/boringssl/crypto/stack/CMakeLists.txt create mode 100644 external/boringssl/crypto/stack/make_macros.sh create mode 100644 external/boringssl/crypto/stack/stack.c create mode 100644 external/boringssl/crypto/test/CMakeLists.txt create mode 100644 external/boringssl/crypto/test/file_test.cc create mode 100644 external/boringssl/crypto/test/file_test.h create mode 100644 external/boringssl/crypto/test/malloc.cc create mode 100644 external/boringssl/crypto/test/scoped_types.h create mode 100644 external/boringssl/crypto/test/test_util.cc create mode 100644 external/boringssl/crypto/test/test_util.h create mode 100644 external/boringssl/crypto/thread.c create mode 100644 external/boringssl/crypto/thread_none.c create mode 100644 external/boringssl/crypto/thread_pthread.c create mode 100644 external/boringssl/crypto/thread_test.c create mode 100644 external/boringssl/crypto/thread_win.c create mode 100644 external/boringssl/crypto/time_support.c create mode 100644 external/boringssl/crypto/x509/CMakeLists.txt create mode 100644 external/boringssl/crypto/x509/a_digest.c create mode 100644 external/boringssl/crypto/x509/a_sign.c create mode 100644 external/boringssl/crypto/x509/a_strex.c create mode 100644 external/boringssl/crypto/x509/a_verify.c create mode 100644 external/boringssl/crypto/x509/algorithm.c create mode 100644 external/boringssl/crypto/x509/asn1_gen.c create mode 100644 external/boringssl/crypto/x509/by_dir.c create mode 100644 external/boringssl/crypto/x509/by_file.c create mode 100644 external/boringssl/crypto/x509/charmap.h create mode 100644 external/boringssl/crypto/x509/i2d_pr.c create mode 100644 external/boringssl/crypto/x509/internal.h create mode 100644 external/boringssl/crypto/x509/pkcs7.c create mode 100644 external/boringssl/crypto/x509/pkcs7_test.c create mode 100644 external/boringssl/crypto/x509/rsa_pss.c create mode 100644 external/boringssl/crypto/x509/t_crl.c create mode 100644 external/boringssl/crypto/x509/t_req.c create mode 100644 external/boringssl/crypto/x509/t_x509.c create mode 100644 external/boringssl/crypto/x509/t_x509a.c create mode 100644 external/boringssl/crypto/x509/vpm_int.h create mode 100644 external/boringssl/crypto/x509/x509.c create mode 100644 external/boringssl/crypto/x509/x509_att.c create mode 100644 external/boringssl/crypto/x509/x509_cmp.c create mode 100644 external/boringssl/crypto/x509/x509_d2.c create mode 100644 external/boringssl/crypto/x509/x509_def.c create mode 100644 external/boringssl/crypto/x509/x509_ext.c create mode 100644 external/boringssl/crypto/x509/x509_lu.c create mode 100644 external/boringssl/crypto/x509/x509_obj.c create mode 100644 external/boringssl/crypto/x509/x509_r2x.c create mode 100644 external/boringssl/crypto/x509/x509_req.c create mode 100644 external/boringssl/crypto/x509/x509_set.c create mode 100644 external/boringssl/crypto/x509/x509_test.cc create mode 100644 external/boringssl/crypto/x509/x509_trs.c create mode 100644 external/boringssl/crypto/x509/x509_txt.c create mode 100644 external/boringssl/crypto/x509/x509_v3.c create mode 100644 external/boringssl/crypto/x509/x509_vfy.c create mode 100644 external/boringssl/crypto/x509/x509_vpm.c create mode 100644 external/boringssl/crypto/x509/x509cset.c create mode 100644 external/boringssl/crypto/x509/x509name.c create mode 100644 external/boringssl/crypto/x509/x509rset.c create mode 100644 external/boringssl/crypto/x509/x509spki.c create mode 100644 external/boringssl/crypto/x509/x509type.c create mode 100644 external/boringssl/crypto/x509/x_algor.c create mode 100644 external/boringssl/crypto/x509/x_all.c create mode 100644 external/boringssl/crypto/x509/x_attrib.c create mode 100644 external/boringssl/crypto/x509/x_crl.c create mode 100644 external/boringssl/crypto/x509/x_exten.c create mode 100644 external/boringssl/crypto/x509/x_info.c create mode 100644 external/boringssl/crypto/x509/x_name.c create mode 100644 external/boringssl/crypto/x509/x_pkey.c create mode 100644 external/boringssl/crypto/x509/x_pubkey.c create mode 100644 external/boringssl/crypto/x509/x_req.c create mode 100644 external/boringssl/crypto/x509/x_sig.c create mode 100644 external/boringssl/crypto/x509/x_spki.c create mode 100644 external/boringssl/crypto/x509/x_val.c create mode 100644 external/boringssl/crypto/x509/x_x509.c create mode 100644 external/boringssl/crypto/x509/x_x509a.c create mode 100644 external/boringssl/crypto/x509v3/CMakeLists.txt create mode 100644 external/boringssl/crypto/x509v3/ext_dat.h create mode 100644 external/boringssl/crypto/x509v3/pcy_cache.c create mode 100644 external/boringssl/crypto/x509v3/pcy_data.c create mode 100644 external/boringssl/crypto/x509v3/pcy_int.h create mode 100644 external/boringssl/crypto/x509v3/pcy_lib.c create mode 100644 external/boringssl/crypto/x509v3/pcy_map.c create mode 100644 external/boringssl/crypto/x509v3/pcy_node.c create mode 100644 external/boringssl/crypto/x509v3/pcy_tree.c create mode 100644 external/boringssl/crypto/x509v3/tab_test.c create mode 100644 external/boringssl/crypto/x509v3/v3_akey.c create mode 100644 external/boringssl/crypto/x509v3/v3_akeya.c create mode 100644 external/boringssl/crypto/x509v3/v3_alt.c create mode 100644 external/boringssl/crypto/x509v3/v3_bcons.c create mode 100644 external/boringssl/crypto/x509v3/v3_bitst.c create mode 100644 external/boringssl/crypto/x509v3/v3_conf.c create mode 100644 external/boringssl/crypto/x509v3/v3_cpols.c create mode 100644 external/boringssl/crypto/x509v3/v3_crld.c create mode 100644 external/boringssl/crypto/x509v3/v3_enum.c create mode 100644 external/boringssl/crypto/x509v3/v3_extku.c create mode 100644 external/boringssl/crypto/x509v3/v3_genn.c create mode 100644 external/boringssl/crypto/x509v3/v3_ia5.c create mode 100644 external/boringssl/crypto/x509v3/v3_info.c create mode 100644 external/boringssl/crypto/x509v3/v3_int.c create mode 100644 external/boringssl/crypto/x509v3/v3_lib.c create mode 100644 external/boringssl/crypto/x509v3/v3_ncons.c create mode 100644 external/boringssl/crypto/x509v3/v3_pci.c create mode 100644 external/boringssl/crypto/x509v3/v3_pcia.c create mode 100644 external/boringssl/crypto/x509v3/v3_pcons.c create mode 100644 external/boringssl/crypto/x509v3/v3_pku.c create mode 100644 external/boringssl/crypto/x509v3/v3_pmaps.c create mode 100644 external/boringssl/crypto/x509v3/v3_prn.c create mode 100644 external/boringssl/crypto/x509v3/v3_purp.c create mode 100644 external/boringssl/crypto/x509v3/v3_skey.c create mode 100644 external/boringssl/crypto/x509v3/v3_sxnet.c create mode 100644 external/boringssl/crypto/x509v3/v3_utl.c create mode 100644 external/boringssl/crypto/x509v3/v3name_test.c create mode 100644 external/boringssl/decrepit/CMakeLists.txt create mode 100644 external/boringssl/decrepit/bio/CMakeLists.txt create mode 100644 external/boringssl/decrepit/bio/base64_bio.c create mode 100644 external/boringssl/decrepit/blowfish/CMakeLists.txt create mode 100644 external/boringssl/decrepit/blowfish/blowfish.c create mode 100644 external/boringssl/decrepit/cast/CMakeLists.txt create mode 100644 external/boringssl/decrepit/cast/cast.c create mode 100644 external/boringssl/decrepit/cast/cast_tables.c create mode 100644 external/boringssl/decrepit/cast/internal.h create mode 100644 external/boringssl/decrepit/des/CMakeLists.txt create mode 100644 external/boringssl/decrepit/des/cfb64ede.c create mode 100644 external/boringssl/decrepit/dh/CMakeLists.txt create mode 100644 external/boringssl/decrepit/dh/dh_decrepit.c create mode 100644 external/boringssl/decrepit/dsa/CMakeLists.txt create mode 100644 external/boringssl/decrepit/dsa/dsa_decrepit.c create mode 100644 external/boringssl/decrepit/evp/CMakeLists.txt create mode 100644 external/boringssl/decrepit/evp/dss1.c create mode 100644 external/boringssl/decrepit/evp/evp_do_all.c create mode 100644 external/boringssl/decrepit/macros.h create mode 100644 external/boringssl/decrepit/obj/CMakeLists.txt create mode 100644 external/boringssl/decrepit/obj/obj_decrepit.c create mode 100644 external/boringssl/decrepit/rc4/CMakeLists.txt create mode 100644 external/boringssl/decrepit/rc4/rc4_decrepit.c create mode 100644 external/boringssl/decrepit/ripemd/CMakeLists.txt create mode 100644 external/boringssl/decrepit/ripemd/internal.h create mode 100644 external/boringssl/decrepit/ripemd/ripemd.c create mode 100644 external/boringssl/decrepit/ripemd/ripemd_test.cc create mode 100644 external/boringssl/decrepit/rsa/CMakeLists.txt create mode 100644 external/boringssl/decrepit/rsa/rsa_decrepit.c create mode 100644 external/boringssl/decrepit/ssl/CMakeLists.txt create mode 100644 external/boringssl/decrepit/ssl/ssl_decrepit.c create mode 100644 external/boringssl/decrepit/x509/CMakeLists.txt create mode 100644 external/boringssl/decrepit/x509/x509_decrepit.c create mode 100644 external/boringssl/decrepit/xts/CMakeLists.txt create mode 100644 external/boringssl/decrepit/xts/xts.c create mode 100644 external/boringssl/fuzz/CMakeLists.txt create mode 100644 external/boringssl/fuzz/cert.cc create mode 100644 external/boringssl/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be create mode 100644 external/boringssl/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f create mode 100644 external/boringssl/fuzz/cert_corpus/031c5183d8c8c560e8e1818ff82aabf33973f770 create mode 100644 external/boringssl/fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408 create mode 100644 external/boringssl/fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fde create mode 100644 external/boringssl/fuzz/cert_corpus/04ed1e2c50886acd723b3a78d4bafd49938bd14d create mode 100644 external/boringssl/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41 create mode 100644 external/boringssl/fuzz/cert_corpus/0694a2168fe7699e2dcabe3386a80bd4209094fc create mode 100644 external/boringssl/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3 create mode 100644 external/boringssl/fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704 create mode 100644 external/boringssl/fuzz/cert_corpus/094d3581e71a4316a567e43e6ebfa63b95196b8e create mode 100644 external/boringssl/fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144 create mode 100644 external/boringssl/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5 create mode 100644 external/boringssl/fuzz/cert_corpus/0b2f2af22568510301982a60fba3763b6ca92409 create mode 100644 external/boringssl/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e create mode 100644 external/boringssl/fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627 create mode 100644 external/boringssl/fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59 create mode 100644 external/boringssl/fuzz/cert_corpus/0c30def9baf58c5be015cede0594b4bd73507f00 create mode 100644 external/boringssl/fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3c create mode 100644 external/boringssl/fuzz/cert_corpus/0db3ab78e42c2aecbc7b898501c4f91ba91c200f create mode 100644 external/boringssl/fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f create mode 100644 external/boringssl/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de create mode 100644 external/boringssl/fuzz/cert_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff create mode 100644 external/boringssl/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad create mode 100644 external/boringssl/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1 create mode 100644 external/boringssl/fuzz/cert_corpus/1108c80f8912d5d9492de40e48dbdb7e44ae4a8c create mode 100644 external/boringssl/fuzz/cert_corpus/1173445eb10e631879bf6b5cc168e2b8fb89dbdf create mode 100644 external/boringssl/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92 create mode 100644 external/boringssl/fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900 create mode 100644 external/boringssl/fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bc create mode 100644 external/boringssl/fuzz/cert_corpus/148fc92ab76dab6ffbb59a544e9174ecf32f187b create mode 100644 external/boringssl/fuzz/cert_corpus/152bd97b8a6e893d704db2947e31f2e7dd7f9c63 create mode 100644 external/boringssl/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb create mode 100644 external/boringssl/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac create mode 100644 external/boringssl/fuzz/cert_corpus/162f227ef1629ac9a11a433bf124d297aedac5ef create mode 100644 external/boringssl/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a create mode 100644 external/boringssl/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938 create mode 100644 external/boringssl/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90 create mode 100644 external/boringssl/fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94e create mode 100644 external/boringssl/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea create mode 100644 external/boringssl/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7 create mode 100644 external/boringssl/fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875 create mode 100644 external/boringssl/fuzz/cert_corpus/1a75d3e2d9ee4c34fb8d7506be6b2d762f6215d9 create mode 100644 external/boringssl/fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8 create mode 100644 external/boringssl/fuzz/cert_corpus/1b9384af3bcfce2b1cb34dcc4541fc1177e18dae create mode 100644 external/boringssl/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7 create mode 100644 external/boringssl/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 create mode 100644 external/boringssl/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0 create mode 100644 external/boringssl/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575 create mode 100644 external/boringssl/fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01 create mode 100644 external/boringssl/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca create mode 100644 external/boringssl/fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189 create mode 100644 external/boringssl/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132 create mode 100644 external/boringssl/fuzz/cert_corpus/22a7767a68debe1a1cfdb43355d2c9332ac88409 create mode 100644 external/boringssl/fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304 create mode 100644 external/boringssl/fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02 create mode 100644 external/boringssl/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed create mode 100644 external/boringssl/fuzz/cert_corpus/24fad8b85d8f1129e12f742472a4895aadef1872 create mode 100644 external/boringssl/fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69e create mode 100644 external/boringssl/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4 create mode 100644 external/boringssl/fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1 create mode 100644 external/boringssl/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4 create mode 100644 external/boringssl/fuzz/cert_corpus/2957f98f3f77110b8a05a8d67a1ff574f090c2b3 create mode 100644 external/boringssl/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 create mode 100644 external/boringssl/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 create mode 100644 external/boringssl/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8 create mode 100644 external/boringssl/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 create mode 100644 external/boringssl/fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f0 create mode 100644 external/boringssl/fuzz/cert_corpus/2c3735c25b884954b3daf5fe573d89f5d516df4a create mode 100644 external/boringssl/fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571 create mode 100644 external/boringssl/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79 create mode 100644 external/boringssl/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 create mode 100644 external/boringssl/fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879 create mode 100644 external/boringssl/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436 create mode 100644 external/boringssl/fuzz/cert_corpus/2e4777559846e771a689f12bdc77806853cf4d08 create mode 100644 external/boringssl/fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42 create mode 100644 external/boringssl/fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572 create mode 100644 external/boringssl/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad create mode 100644 external/boringssl/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b create mode 100644 external/boringssl/fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1 create mode 100644 external/boringssl/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b create mode 100644 external/boringssl/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd create mode 100644 external/boringssl/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06 create mode 100644 external/boringssl/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91 create mode 100644 external/boringssl/fuzz/cert_corpus/3663d7a7c4840fccf48c134a13eed5156b44055e create mode 100644 external/boringssl/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9 create mode 100644 external/boringssl/fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17f create mode 100644 external/boringssl/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0 create mode 100644 external/boringssl/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7 create mode 100644 external/boringssl/fuzz/cert_corpus/37ffecbaa9a8f5540d94963beb62d93e8f1c568d create mode 100644 external/boringssl/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c create mode 100644 external/boringssl/fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6 create mode 100644 external/boringssl/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4 create mode 100644 external/boringssl/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee create mode 100644 external/boringssl/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33 create mode 100644 external/boringssl/fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541 create mode 100644 external/boringssl/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151 create mode 100644 external/boringssl/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537 create mode 100644 external/boringssl/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d create mode 100644 external/boringssl/fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137 create mode 100644 external/boringssl/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645 create mode 100644 external/boringssl/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a create mode 100644 external/boringssl/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934 create mode 100644 external/boringssl/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab create mode 100644 external/boringssl/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c create mode 100644 external/boringssl/fuzz/cert_corpus/4257efd87e9368cde94e8e321ebff4f3a623dd5c create mode 100644 external/boringssl/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619 create mode 100644 external/boringssl/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6 create mode 100644 external/boringssl/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3 create mode 100644 external/boringssl/fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866 create mode 100644 external/boringssl/fuzz/cert_corpus/457c25ce787e34b315d3b161a8b478a5e793c3c4 create mode 100644 external/boringssl/fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbb create mode 100644 external/boringssl/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c create mode 100644 external/boringssl/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b create mode 100644 external/boringssl/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf create mode 100644 external/boringssl/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2 create mode 100644 external/boringssl/fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693ad create mode 100644 external/boringssl/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc create mode 100644 external/boringssl/fuzz/cert_corpus/484c387f1936612f6e742f10775fa81593cb0c47 create mode 100644 external/boringssl/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90 create mode 100644 external/boringssl/fuzz/cert_corpus/4a59656c14d04ce913197e47cde59133db0401c8 create mode 100644 external/boringssl/fuzz/cert_corpus/4a7220ebd75b74c4b91bbde748ea273342e7d306 create mode 100644 external/boringssl/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd create mode 100644 external/boringssl/fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5 create mode 100644 external/boringssl/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 create mode 100644 external/boringssl/fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5 create mode 100644 external/boringssl/fuzz/cert_corpus/4bea495c65f278e4ec1b343819a713f062aaac99 create mode 100644 external/boringssl/fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6 create mode 100644 external/boringssl/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84 create mode 100644 external/boringssl/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 create mode 100644 external/boringssl/fuzz/cert_corpus/4cef0705d69922b19e4f50c16446115d03691379 create mode 100644 external/boringssl/fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057 create mode 100644 external/boringssl/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90 create mode 100644 external/boringssl/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c create mode 100644 external/boringssl/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a create mode 100644 external/boringssl/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0 create mode 100644 external/boringssl/fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854 create mode 100644 external/boringssl/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833 create mode 100644 external/boringssl/fuzz/cert_corpus/536b9cd5f18e73b30687908443036be7a1b108b0 create mode 100644 external/boringssl/fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2f create mode 100644 external/boringssl/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23 create mode 100644 external/boringssl/fuzz/cert_corpus/54faf9d362f22ac220377a9d478731301876830d create mode 100644 external/boringssl/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 create mode 100644 external/boringssl/fuzz/cert_corpus/55ff515a21332c377e8682bb0f05d4a36595cb18 create mode 100644 external/boringssl/fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77caf create mode 100644 external/boringssl/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b create mode 100644 external/boringssl/fuzz/cert_corpus/56ef359b39b367bc94f66501729907dfd8fb8425 create mode 100644 external/boringssl/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 create mode 100644 external/boringssl/fuzz/cert_corpus/5a7baa69f7c27ed50c560f427370910220cf4073 create mode 100644 external/boringssl/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5 create mode 100644 external/boringssl/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 create mode 100644 external/boringssl/fuzz/cert_corpus/5c7389e097519d3d2c974b7d082344c6fdb9e74b create mode 100644 external/boringssl/fuzz/cert_corpus/5ccb2368d4f51967b4d79b062103604a0e73c6ab create mode 100644 external/boringssl/fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132b create mode 100644 external/boringssl/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 create mode 100644 external/boringssl/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf create mode 100644 external/boringssl/fuzz/cert_corpus/5d64f19209be8be3ce3e914b475db34591d7a985 create mode 100644 external/boringssl/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224 create mode 100644 external/boringssl/fuzz/cert_corpus/5f6a0d4e63e434e50dbf1159514610e031afbbc9 create mode 100644 external/boringssl/fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb create mode 100644 external/boringssl/fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31 create mode 100644 external/boringssl/fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5b create mode 100644 external/boringssl/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 create mode 100644 external/boringssl/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9 create mode 100644 external/boringssl/fuzz/cert_corpus/6118a3fcc0337a2cae92be95b87dcdc47a2c53c9 create mode 100644 external/boringssl/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337 create mode 100644 external/boringssl/fuzz/cert_corpus/64a9ce67fccd9c0a3b2ff3d02ea9afbe5619b41f create mode 100644 external/boringssl/fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715 create mode 100644 external/boringssl/fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719b create mode 100644 external/boringssl/fuzz/cert_corpus/65769e24f85a4467ff67707ede0c56b5e7046687 create mode 100644 external/boringssl/fuzz/cert_corpus/65b1bfb6b449b875079f932a6075771dba978141 create mode 100644 external/boringssl/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33 create mode 100644 external/boringssl/fuzz/cert_corpus/66cb9a69e7289f878d3f9bdb235bb4ad97e138b0 create mode 100644 external/boringssl/fuzz/cert_corpus/67c6b2d857ae3edc271adac024751559bed7ae97 create mode 100644 external/boringssl/fuzz/cert_corpus/67f672ab618d2facc0092cd32837cc04e5d37216 create mode 100644 external/boringssl/fuzz/cert_corpus/6869834d4b7c77e0bd7ce160876197a3c9be7040 create mode 100644 external/boringssl/fuzz/cert_corpus/693913decd386589e4d4212fc498714506d667f0 create mode 100644 external/boringssl/fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148 create mode 100644 external/boringssl/fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1 create mode 100644 external/boringssl/fuzz/cert_corpus/6f0d97a3ed2a4c3c330edb10959f005a553d08f4 create mode 100644 external/boringssl/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06 create mode 100644 external/boringssl/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d create mode 100644 external/boringssl/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd create mode 100644 external/boringssl/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 create mode 100644 external/boringssl/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744 create mode 100644 external/boringssl/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3 create mode 100644 external/boringssl/fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330 create mode 100644 external/boringssl/fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5d create mode 100644 external/boringssl/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 create mode 100644 external/boringssl/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 create mode 100644 external/boringssl/fuzz/cert_corpus/7345d2f36ce35f7aaeb3f3c62a2b37f55dfd7af7 create mode 100644 external/boringssl/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224 create mode 100644 external/boringssl/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c create mode 100644 external/boringssl/fuzz/cert_corpus/74287c085825b190ed3cf50ad0f5beec7cc07edd create mode 100644 external/boringssl/fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd create mode 100644 external/boringssl/fuzz/cert_corpus/7685b3e299f2cce95aab0d8559fd45d8198f5da2 create mode 100644 external/boringssl/fuzz/cert_corpus/771688184c18822e2182b18bb1ec853a88262659 create mode 100644 external/boringssl/fuzz/cert_corpus/772739edb5a338fade2b33ed8c4c7e5c3856e7bd create mode 100644 external/boringssl/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 create mode 100644 external/boringssl/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9 create mode 100644 external/boringssl/fuzz/cert_corpus/78fa5096155d1b72a074a486cf7ace40a4c92f1f create mode 100644 external/boringssl/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 create mode 100644 external/boringssl/fuzz/cert_corpus/79fe694f60433debeb203f01dbacefcde6e9483f create mode 100644 external/boringssl/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1 create mode 100644 external/boringssl/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144 create mode 100644 external/boringssl/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847 create mode 100644 external/boringssl/fuzz/cert_corpus/7e87ff06a8c83b1195fb15a9d599abfe28b94cbf create mode 100644 external/boringssl/fuzz/cert_corpus/7eb1f7349c812a0ed94fe21f9900600516164b17 create mode 100644 external/boringssl/fuzz/cert_corpus/7ecb46c93915184be12fa3cbaac3b65072116242 create mode 100644 external/boringssl/fuzz/cert_corpus/806fd814b69bc6511d7f6e1a3bc762d14a56364a create mode 100644 external/boringssl/fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5f create mode 100644 external/boringssl/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb create mode 100644 external/boringssl/fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6 create mode 100644 external/boringssl/fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988b create mode 100644 external/boringssl/fuzz/cert_corpus/8217aa968f0050b2fb1aac92ae6f377c41c3952b create mode 100644 external/boringssl/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1 create mode 100644 external/boringssl/fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48 create mode 100644 external/boringssl/fuzz/cert_corpus/848426625248d49961481ba4616c501a808983ac create mode 100644 external/boringssl/fuzz/cert_corpus/84882a41d7892f52a3145178b9ff8ad6947ddbf4 create mode 100644 external/boringssl/fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264def create mode 100644 external/boringssl/fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85 create mode 100644 external/boringssl/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 create mode 100644 external/boringssl/fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57f create mode 100644 external/boringssl/fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668 create mode 100644 external/boringssl/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35 create mode 100644 external/boringssl/fuzz/cert_corpus/8853ff143e14ef222a6c7044ea50992b53ed7387 create mode 100644 external/boringssl/fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050ead create mode 100644 external/boringssl/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d create mode 100644 external/boringssl/fuzz/cert_corpus/88e90e49acd2ab796a48eda68f66529dd4206671 create mode 100644 external/boringssl/fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8f create mode 100644 external/boringssl/fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fade create mode 100644 external/boringssl/fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665 create mode 100644 external/boringssl/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431 create mode 100644 external/boringssl/fuzz/cert_corpus/8b188b379875299b1f6ca0501cf758b3a313a7d8 create mode 100644 external/boringssl/fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4d create mode 100644 external/boringssl/fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3 create mode 100644 external/boringssl/fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538 create mode 100644 external/boringssl/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00 create mode 100644 external/boringssl/fuzz/cert_corpus/9070df87024c0167e6a1bd9512f698d3a31ca0b1 create mode 100644 external/boringssl/fuzz/cert_corpus/90fbdf2d500b38c15e3364d041484cf065cba9df create mode 100644 external/boringssl/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a create mode 100644 external/boringssl/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad create mode 100644 external/boringssl/fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394 create mode 100644 external/boringssl/fuzz/cert_corpus/953b46659c6224c0068a9ddb3fa7b0a74f89af3e create mode 100644 external/boringssl/fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6 create mode 100644 external/boringssl/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae create mode 100644 external/boringssl/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 create mode 100644 external/boringssl/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd create mode 100644 external/boringssl/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad create mode 100644 external/boringssl/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db create mode 100644 external/boringssl/fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc631 create mode 100644 external/boringssl/fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9 create mode 100644 external/boringssl/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079 create mode 100644 external/boringssl/fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3 create mode 100644 external/boringssl/fuzz/cert_corpus/9baa5f344ecd37e2762cb8a7497709b78d69cae6 create mode 100644 external/boringssl/fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7d create mode 100644 external/boringssl/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd create mode 100644 external/boringssl/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 create mode 100644 external/boringssl/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3 create mode 100644 external/boringssl/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff create mode 100644 external/boringssl/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420 create mode 100644 external/boringssl/fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9 create mode 100644 external/boringssl/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029 create mode 100644 external/boringssl/fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f create mode 100644 external/boringssl/fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681 create mode 100644 external/boringssl/fuzz/cert_corpus/a37c3ee4668153e5ef9c272d43a2545a75b36854 create mode 100644 external/boringssl/fuzz/cert_corpus/a46eda9b97888af5263bc32293f940a8c2125ac3 create mode 100644 external/boringssl/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 create mode 100644 external/boringssl/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 create mode 100644 external/boringssl/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a create mode 100644 external/boringssl/fuzz/cert_corpus/a6447b7b3c50340aa14feb960245856ddeebc2cf create mode 100644 external/boringssl/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d create mode 100644 external/boringssl/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a create mode 100644 external/boringssl/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb create mode 100644 external/boringssl/fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcd create mode 100644 external/boringssl/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457 create mode 100644 external/boringssl/fuzz/cert_corpus/aa94b8c126db37057eba60ebf9ee8424c4dcd931 create mode 100644 external/boringssl/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7 create mode 100644 external/boringssl/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a create mode 100644 external/boringssl/fuzz/cert_corpus/ad0875493831e5d809ec58af56dc27736d8da4cf create mode 100644 external/boringssl/fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0a create mode 100644 external/boringssl/fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2 create mode 100644 external/boringssl/fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9 create mode 100644 external/boringssl/fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746 create mode 100644 external/boringssl/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b create mode 100644 external/boringssl/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb create mode 100644 external/boringssl/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a create mode 100644 external/boringssl/fuzz/cert_corpus/b0bbe893c3557ffe322c9acbb268f58bd6f6ab9d create mode 100644 external/boringssl/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 create mode 100644 external/boringssl/fuzz/cert_corpus/b255b3d96ff0a405b5c782cd18fbc50034d09793 create mode 100644 external/boringssl/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63 create mode 100644 external/boringssl/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 create mode 100644 external/boringssl/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 create mode 100644 external/boringssl/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024 create mode 100644 external/boringssl/fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8 create mode 100644 external/boringssl/fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74 create mode 100644 external/boringssl/fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902 create mode 100644 external/boringssl/fuzz/cert_corpus/b5f5a28954d2634baf685a1790ce013ca0f0f951 create mode 100644 external/boringssl/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 create mode 100644 external/boringssl/fuzz/cert_corpus/b63a8d0e7c1848019b4e4e8e19d14adec00b7c19 create mode 100644 external/boringssl/fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84 create mode 100644 external/boringssl/fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fda create mode 100644 external/boringssl/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac create mode 100644 external/boringssl/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 create mode 100644 external/boringssl/fuzz/cert_corpus/b88401cca46b7cc9cf588dbec641411101bbce68 create mode 100644 external/boringssl/fuzz/cert_corpus/b8c68e6426d5993b9c08d0384dce5d52014254a6 create mode 100644 external/boringssl/fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2 create mode 100644 external/boringssl/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399 create mode 100644 external/boringssl/fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0 create mode 100644 external/boringssl/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e create mode 100644 external/boringssl/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068 create mode 100644 external/boringssl/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92 create mode 100644 external/boringssl/fuzz/cert_corpus/bd32136e6ec853a56e70060a2c308187b8fccf65 create mode 100644 external/boringssl/fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767c create mode 100644 external/boringssl/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def create mode 100644 external/boringssl/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf create mode 100644 external/boringssl/fuzz/cert_corpus/be96bcebf50e143552339a23071c9994bb7b5548 create mode 100644 external/boringssl/fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2 create mode 100644 external/boringssl/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28 create mode 100644 external/boringssl/fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851b create mode 100644 external/boringssl/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea create mode 100644 external/boringssl/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6 create mode 100644 external/boringssl/fuzz/cert_corpus/c3c6d8be363e9b8535dc6586a6b01122efefdea9 create mode 100644 external/boringssl/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b create mode 100644 external/boringssl/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 create mode 100644 external/boringssl/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3 create mode 100644 external/boringssl/fuzz/cert_corpus/c47cc42321d347f0b8596e94c53ddfc0c5a90a88 create mode 100644 external/boringssl/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd create mode 100644 external/boringssl/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008 create mode 100644 external/boringssl/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040 create mode 100644 external/boringssl/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 create mode 100644 external/boringssl/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744 create mode 100644 external/boringssl/fuzz/cert_corpus/c6bb980166717e341bc7628fdcf7e6857f42b78e create mode 100644 external/boringssl/fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fb create mode 100644 external/boringssl/fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54 create mode 100644 external/boringssl/fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8 create mode 100644 external/boringssl/fuzz/cert_corpus/cc70087dae81f66673015fe1f97b13b0f1d7256d create mode 100644 external/boringssl/fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644 create mode 100644 external/boringssl/fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18ca create mode 100644 external/boringssl/fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9a create mode 100644 external/boringssl/fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1ca create mode 100644 external/boringssl/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f create mode 100644 external/boringssl/fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0d create mode 100644 external/boringssl/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c create mode 100644 external/boringssl/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61 create mode 100644 external/boringssl/fuzz/cert_corpus/d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 create mode 100644 external/boringssl/fuzz/cert_corpus/d51782b160d3dacee93a1dc34cfec9a7ca4a6c53 create mode 100644 external/boringssl/fuzz/cert_corpus/d5c2fed75bc049b570bd445b9461a1595f880dca create mode 100644 external/boringssl/fuzz/cert_corpus/d5c3e609d1685e2a11e63622d71cba7cc8a73590 create mode 100644 external/boringssl/fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15 create mode 100644 external/boringssl/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d create mode 100644 external/boringssl/fuzz/cert_corpus/d6df7b56969b3f2bd6c323aca98179f1f3ef3396 create mode 100644 external/boringssl/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d create mode 100644 external/boringssl/fuzz/cert_corpus/d7ba4e58caa05b0c3bd0f5258adf1429d022632f create mode 100644 external/boringssl/fuzz/cert_corpus/d805c1da8681e325ad44cf57dbac466ca77efca8 create mode 100644 external/boringssl/fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796 create mode 100644 external/boringssl/fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1 create mode 100644 external/boringssl/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee create mode 100644 external/boringssl/fuzz/cert_corpus/de05b31a05846f00be753f15be9242b01396a553 create mode 100644 external/boringssl/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674 create mode 100644 external/boringssl/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e create mode 100644 external/boringssl/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 create mode 100644 external/boringssl/fuzz/cert_corpus/e180125371c88bbab75d9aac4d6b1144e0f0683e create mode 100644 external/boringssl/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945 create mode 100644 external/boringssl/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 create mode 100644 external/boringssl/fuzz/cert_corpus/e662bc8b0f1bcea6081c65fc1195e6df53a51961 create mode 100644 external/boringssl/fuzz/cert_corpus/e67cc75ea22aec3e31ac08718a0e8ebb49d0378b create mode 100644 external/boringssl/fuzz/cert_corpus/e6d0bda14de5fabf61d6a77ed9de9dc32751c193 create mode 100644 external/boringssl/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3 create mode 100644 external/boringssl/fuzz/cert_corpus/e9617db6d8b651b46ea1ef7b904887d3259d8721 create mode 100644 external/boringssl/fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419 create mode 100644 external/boringssl/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229 create mode 100644 external/boringssl/fuzz/cert_corpus/ebb2f919adba543e9f61ba5ffd13e89c9422f70a create mode 100644 external/boringssl/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf create mode 100644 external/boringssl/fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794 create mode 100644 external/boringssl/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22 create mode 100644 external/boringssl/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2 create mode 100644 external/boringssl/fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cd create mode 100644 external/boringssl/fuzz/cert_corpus/ecac00e857f10a143e5760a8d027498fdb46cbf4 create mode 100644 external/boringssl/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53 create mode 100644 external/boringssl/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100 create mode 100644 external/boringssl/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95 create mode 100644 external/boringssl/fuzz/cert_corpus/efb28c035f9c8a62a312dfe83434cddbc51b4c8a create mode 100644 external/boringssl/fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93 create mode 100644 external/boringssl/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44 create mode 100644 external/boringssl/fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987c create mode 100644 external/boringssl/fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119 create mode 100644 external/boringssl/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741 create mode 100644 external/boringssl/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8 create mode 100644 external/boringssl/fuzz/cert_corpus/f34b279011e9a03e95b85f6a8d5e2a59089fe516 create mode 100644 external/boringssl/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1 create mode 100644 external/boringssl/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b create mode 100644 external/boringssl/fuzz/cert_corpus/f8e817dc5c2b1f27d31240841ade404d15606742 create mode 100644 external/boringssl/fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0 create mode 100644 external/boringssl/fuzz/cert_corpus/fca0bbdfab4ad790670f079ac242c12a5c7fa58a create mode 100644 external/boringssl/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac create mode 100644 external/boringssl/fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547 create mode 100644 external/boringssl/fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2 create mode 100644 external/boringssl/fuzz/cert_corpus/ff46d1b4923b92b30fa6fd9a7e429ad1cb1f9e7f create mode 100644 external/boringssl/fuzz/client.cc create mode 100644 external/boringssl/fuzz/client_corpus/00717d11ddde89f0895bf72de8de3bf99d1b5c46 create mode 100644 external/boringssl/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c create mode 100644 external/boringssl/fuzz/client_corpus/00a71e9e98b44548faef02dc058b357edeaf6e88 create mode 100644 external/boringssl/fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86 create mode 100644 external/boringssl/fuzz/client_corpus/01e050c8b311caa72bebb132b9fe98e22ac56682 create mode 100644 external/boringssl/fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801dee create mode 100644 external/boringssl/fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678 create mode 100644 external/boringssl/fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16 create mode 100644 external/boringssl/fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2 create mode 100644 external/boringssl/fuzz/client_corpus/031f30a25eb84fc9585ffa6d9f8ad2a6910a450b create mode 100644 external/boringssl/fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05 create mode 100644 external/boringssl/fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45 create mode 100644 external/boringssl/fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5 create mode 100644 external/boringssl/fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263 create mode 100644 external/boringssl/fuzz/client_corpus/046d8a2ca8e3e68dc1b555e46ac4d4a6d2491982 create mode 100644 external/boringssl/fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865 create mode 100644 external/boringssl/fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083 create mode 100644 external/boringssl/fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078 create mode 100644 external/boringssl/fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520 create mode 100644 external/boringssl/fuzz/client_corpus/05580dbaccccb94d23cbfc8bab5a1d299ebe79ee create mode 100644 external/boringssl/fuzz/client_corpus/05a05196a8e0958f1ba744d122208d337a8696fa create mode 100644 external/boringssl/fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8 create mode 100644 external/boringssl/fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343 create mode 100644 external/boringssl/fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6 create mode 100644 external/boringssl/fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3 create mode 100644 external/boringssl/fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0d create mode 100644 external/boringssl/fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968f create mode 100644 external/boringssl/fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85 create mode 100644 external/boringssl/fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0a create mode 100644 external/boringssl/fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35 create mode 100644 external/boringssl/fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740 create mode 100644 external/boringssl/fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903 create mode 100644 external/boringssl/fuzz/client_corpus/09225c1125fed526539a962ff46972676518fa34 create mode 100644 external/boringssl/fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145 create mode 100644 external/boringssl/fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099 create mode 100644 external/boringssl/fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5 create mode 100644 external/boringssl/fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103 create mode 100644 external/boringssl/fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0 create mode 100644 external/boringssl/fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192 create mode 100644 external/boringssl/fuzz/client_corpus/0b251113d82bdc624c418ca3e9a822af3f43f4bc create mode 100644 external/boringssl/fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2 create mode 100644 external/boringssl/fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629d create mode 100644 external/boringssl/fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929 create mode 100644 external/boringssl/fuzz/client_corpus/0d9891ca130cb689545acefd20ccc979e4b53f27 create mode 100644 external/boringssl/fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51d create mode 100644 external/boringssl/fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28 create mode 100644 external/boringssl/fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9f create mode 100644 external/boringssl/fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04ad create mode 100644 external/boringssl/fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538 create mode 100644 external/boringssl/fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370 create mode 100644 external/boringssl/fuzz/client_corpus/10d8e6931cf75e896c8a6ec1081df869e30310e1 create mode 100644 external/boringssl/fuzz/client_corpus/111bb472fcf4fc134af5ec3c189f43ef9ef19b36 create mode 100644 external/boringssl/fuzz/client_corpus/1175419b73c59b028cb36d263fe31dddff6ed54d create mode 100644 external/boringssl/fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720 create mode 100644 external/boringssl/fuzz/client_corpus/119735b91048ae492dfb7459aaa01d7fe13c767d create mode 100644 external/boringssl/fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8f create mode 100644 external/boringssl/fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8 create mode 100644 external/boringssl/fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4a create mode 100644 external/boringssl/fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1b create mode 100644 external/boringssl/fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5e create mode 100644 external/boringssl/fuzz/client_corpus/129f293ffb471c54f0a65ebe68e8c03ae20edc63 create mode 100644 external/boringssl/fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbb create mode 100644 external/boringssl/fuzz/client_corpus/12b0df532889077124403153935a3d4902a6268d create mode 100644 external/boringssl/fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526 create mode 100644 external/boringssl/fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49 create mode 100644 external/boringssl/fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36 create mode 100644 external/boringssl/fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95e create mode 100644 external/boringssl/fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063b create mode 100644 external/boringssl/fuzz/client_corpus/15a54d5f346c2fd9fa3da6f73cee5db2c7952f68 create mode 100644 external/boringssl/fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6 create mode 100644 external/boringssl/fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9 create mode 100644 external/boringssl/fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bf create mode 100644 external/boringssl/fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0d create mode 100644 external/boringssl/fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644 create mode 100644 external/boringssl/fuzz/client_corpus/16dc8080d01278cfb39ee1c6836fe9d3b7e55436 create mode 100644 external/boringssl/fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7 create mode 100644 external/boringssl/fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a create mode 100644 external/boringssl/fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801 create mode 100644 external/boringssl/fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6dec create mode 100644 external/boringssl/fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4ae create mode 100644 external/boringssl/fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6d create mode 100644 external/boringssl/fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1d create mode 100644 external/boringssl/fuzz/client_corpus/189eec7d1e6d85b7cbc91c0320ea8643426e3ccd create mode 100644 external/boringssl/fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924 create mode 100644 external/boringssl/fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7f create mode 100644 external/boringssl/fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956 create mode 100644 external/boringssl/fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2 create mode 100644 external/boringssl/fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38 create mode 100644 external/boringssl/fuzz/client_corpus/1c7a97739e894d39ece462a80f4039f3c778a3ef create mode 100644 external/boringssl/fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00b create mode 100644 external/boringssl/fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6 create mode 100644 external/boringssl/fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069 create mode 100644 external/boringssl/fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2 create mode 100644 external/boringssl/fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507 create mode 100644 external/boringssl/fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7 create mode 100644 external/boringssl/fuzz/client_corpus/1efe14c5799b31f2dc4c413643235c9ec5086e06 create mode 100644 external/boringssl/fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92 create mode 100644 external/boringssl/fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55da create mode 100644 external/boringssl/fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ff create mode 100644 external/boringssl/fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94 create mode 100644 external/boringssl/fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b create mode 100644 external/boringssl/fuzz/client_corpus/212aefea1187a824be184640c2c673c5b85fb6e4 create mode 100644 external/boringssl/fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73a create mode 100644 external/boringssl/fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819 create mode 100644 external/boringssl/fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647d create mode 100644 external/boringssl/fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7 create mode 100644 external/boringssl/fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89 create mode 100644 external/boringssl/fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92 create mode 100644 external/boringssl/fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625 create mode 100644 external/boringssl/fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560 create mode 100644 external/boringssl/fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0b create mode 100644 external/boringssl/fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dc create mode 100644 external/boringssl/fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740 create mode 100644 external/boringssl/fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4 create mode 100644 external/boringssl/fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79 create mode 100644 external/boringssl/fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873da create mode 100644 external/boringssl/fuzz/client_corpus/262cc348aa328fa0e256c1ee38a13bf32be45080 create mode 100644 external/boringssl/fuzz/client_corpus/2640d5ce7a30e232909199583946b0d0e93639b9 create mode 100644 external/boringssl/fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129e create mode 100644 external/boringssl/fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bb create mode 100644 external/boringssl/fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296d create mode 100644 external/boringssl/fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2 create mode 100644 external/boringssl/fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1 create mode 100644 external/boringssl/fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7 create mode 100644 external/boringssl/fuzz/client_corpus/295259cda114ddc75587c4237e42d2cb3bd58165 create mode 100644 external/boringssl/fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807 create mode 100644 external/boringssl/fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857f create mode 100644 external/boringssl/fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9c create mode 100644 external/boringssl/fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8a create mode 100644 external/boringssl/fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205 create mode 100644 external/boringssl/fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6 create mode 100644 external/boringssl/fuzz/client_corpus/2c0ba9f07133ff5c9f25f2518a375ece8a4b2ab7 create mode 100644 external/boringssl/fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552 create mode 100644 external/boringssl/fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8 create mode 100644 external/boringssl/fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020 create mode 100644 external/boringssl/fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aa create mode 100644 external/boringssl/fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9 create mode 100644 external/boringssl/fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5 create mode 100644 external/boringssl/fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40e create mode 100644 external/boringssl/fuzz/client_corpus/2e7f99689d1ac0a28adf0785f28946561b3a9076 create mode 100644 external/boringssl/fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248 create mode 100644 external/boringssl/fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a create mode 100644 external/boringssl/fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66e create mode 100644 external/boringssl/fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825 create mode 100644 external/boringssl/fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224 create mode 100644 external/boringssl/fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6a create mode 100644 external/boringssl/fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3 create mode 100644 external/boringssl/fuzz/client_corpus/31bd0841f052c324db7b6bcde7e5517b289708d7 create mode 100644 external/boringssl/fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8 create mode 100644 external/boringssl/fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501 create mode 100644 external/boringssl/fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39 create mode 100644 external/boringssl/fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7c create mode 100644 external/boringssl/fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02 create mode 100644 external/boringssl/fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31 create mode 100644 external/boringssl/fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9d create mode 100644 external/boringssl/fuzz/client_corpus/34edfdaf9801227520aef18e911c0dd28cad2dde create mode 100644 external/boringssl/fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203 create mode 100644 external/boringssl/fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbe create mode 100644 external/boringssl/fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725b create mode 100644 external/boringssl/fuzz/client_corpus/36e6dd737b0f9e0c28acd58660006ea5ba3e08a3 create mode 100644 external/boringssl/fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f create mode 100644 external/boringssl/fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8 create mode 100644 external/boringssl/fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14 create mode 100644 external/boringssl/fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12 create mode 100644 external/boringssl/fuzz/client_corpus/38c4742b3533fb5fe2aa75661055614683a90b42 create mode 100644 external/boringssl/fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5 create mode 100644 external/boringssl/fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6d create mode 100644 external/boringssl/fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308 create mode 100644 external/boringssl/fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4 create mode 100644 external/boringssl/fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656 create mode 100644 external/boringssl/fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8 create mode 100644 external/boringssl/fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809 create mode 100644 external/boringssl/fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afb create mode 100644 external/boringssl/fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491 create mode 100644 external/boringssl/fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438c create mode 100644 external/boringssl/fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37c create mode 100644 external/boringssl/fuzz/client_corpus/3ae3f333e3883de4de59431f0bde46aaae04dc32 create mode 100644 external/boringssl/fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834c create mode 100644 external/boringssl/fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990 create mode 100644 external/boringssl/fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba create mode 100644 external/boringssl/fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512a create mode 100644 external/boringssl/fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5af create mode 100644 external/boringssl/fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495 create mode 100644 external/boringssl/fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5 create mode 100644 external/boringssl/fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353 create mode 100644 external/boringssl/fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988c create mode 100644 external/boringssl/fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13 create mode 100644 external/boringssl/fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3beb create mode 100644 external/boringssl/fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80 create mode 100644 external/boringssl/fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0 create mode 100644 external/boringssl/fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6f create mode 100644 external/boringssl/fuzz/client_corpus/40515498756f4fac616ddc3ac4c2669ea5a8771f create mode 100644 external/boringssl/fuzz/client_corpus/405b2eaa9f8a6ec9aebcaa7d9897c1be18bf9b57 create mode 100644 external/boringssl/fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5b create mode 100644 external/boringssl/fuzz/client_corpus/41b22775bbf5e9716b641b963830a1f35029b400 create mode 100644 external/boringssl/fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5 create mode 100644 external/boringssl/fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182 create mode 100644 external/boringssl/fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5a create mode 100644 external/boringssl/fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fb create mode 100644 external/boringssl/fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bd create mode 100644 external/boringssl/fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8 create mode 100644 external/boringssl/fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5 create mode 100644 external/boringssl/fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872b create mode 100644 external/boringssl/fuzz/client_corpus/4589942d410d038d7739511c3fc862bfaf6f5d55 create mode 100644 external/boringssl/fuzz/client_corpus/458e6fe51ffd10f4f003507da3d34105ff4ba41d create mode 100644 external/boringssl/fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64 create mode 100644 external/boringssl/fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8 create mode 100644 external/boringssl/fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252 create mode 100644 external/boringssl/fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4 create mode 100644 external/boringssl/fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1 create mode 100644 external/boringssl/fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cb create mode 100644 external/boringssl/fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8 create mode 100644 external/boringssl/fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552c create mode 100644 external/boringssl/fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418 create mode 100644 external/boringssl/fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54 create mode 100644 external/boringssl/fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01d create mode 100644 external/boringssl/fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77 create mode 100644 external/boringssl/fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4e create mode 100644 external/boringssl/fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80 create mode 100644 external/boringssl/fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35e create mode 100644 external/boringssl/fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfd create mode 100644 external/boringssl/fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0 create mode 100644 external/boringssl/fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8a create mode 100644 external/boringssl/fuzz/client_corpus/4ab06c821f1a0b5d761ecf299708867e4ca99e9b create mode 100644 external/boringssl/fuzz/client_corpus/4ad50b5ec8b4abc82f90962f6d2a845720fc5b5e create mode 100644 external/boringssl/fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432 create mode 100644 external/boringssl/fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714 create mode 100644 external/boringssl/fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35 create mode 100644 external/boringssl/fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412 create mode 100644 external/boringssl/fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178 create mode 100644 external/boringssl/fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42 create mode 100644 external/boringssl/fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc create mode 100644 external/boringssl/fuzz/client_corpus/4c7f90f4d64c6ef5968dedca30385c5cf76f3972 create mode 100644 external/boringssl/fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479 create mode 100644 external/boringssl/fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866e create mode 100644 external/boringssl/fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cf create mode 100644 external/boringssl/fuzz/client_corpus/4d8c1b4c5e122c2b8255b65e0bdb80ef9fa1573c create mode 100644 external/boringssl/fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbe create mode 100644 external/boringssl/fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32 create mode 100644 external/boringssl/fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019 create mode 100644 external/boringssl/fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249b create mode 100644 external/boringssl/fuzz/client_corpus/4ea847253da2a1a1153634efa3d904a35c59f4a1 create mode 100644 external/boringssl/fuzz/client_corpus/4f041d38c50cd4d7f6a65b8a3c0386ed8e62b97f create mode 100644 external/boringssl/fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13 create mode 100644 external/boringssl/fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71 create mode 100644 external/boringssl/fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9 create mode 100644 external/boringssl/fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261d create mode 100644 external/boringssl/fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55 create mode 100644 external/boringssl/fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1 create mode 100644 external/boringssl/fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebc create mode 100644 external/boringssl/fuzz/client_corpus/51a55b3718f12f1a65110f86eddf8f0c81ce148e create mode 100644 external/boringssl/fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183 create mode 100644 external/boringssl/fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78 create mode 100644 external/boringssl/fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3 create mode 100644 external/boringssl/fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9 create mode 100644 external/boringssl/fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14 create mode 100644 external/boringssl/fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350 create mode 100644 external/boringssl/fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97 create mode 100644 external/boringssl/fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1 create mode 100644 external/boringssl/fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306 create mode 100644 external/boringssl/fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608a create mode 100644 external/boringssl/fuzz/client_corpus/5607123e29f461b258f5ba9bc32772766d09365f create mode 100644 external/boringssl/fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44 create mode 100644 external/boringssl/fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9c create mode 100644 external/boringssl/fuzz/client_corpus/57414bd14950858020832e058d5df0e476472075 create mode 100644 external/boringssl/fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374a create mode 100644 external/boringssl/fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0 create mode 100644 external/boringssl/fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449 create mode 100644 external/boringssl/fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9 create mode 100644 external/boringssl/fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2 create mode 100644 external/boringssl/fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4c create mode 100644 external/boringssl/fuzz/client_corpus/58cac50fb8d0c0a7fd30fea7c8f4b6eeb618604d create mode 100644 external/boringssl/fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87a create mode 100644 external/boringssl/fuzz/client_corpus/59ef60353ba39b1bc59b5a2b514d4a0ebce56a86 create mode 100644 external/boringssl/fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47a create mode 100644 external/boringssl/fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5 create mode 100644 external/boringssl/fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fa create mode 100644 external/boringssl/fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2 create mode 100644 external/boringssl/fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6f create mode 100644 external/boringssl/fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0 create mode 100644 external/boringssl/fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635 create mode 100644 external/boringssl/fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77b create mode 100644 external/boringssl/fuzz/client_corpus/5c583e55833688cc4f7f6f425147ef3734ad269a create mode 100644 external/boringssl/fuzz/client_corpus/5c843d345a3a7763930444707181aee5cd191438 create mode 100644 external/boringssl/fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebae create mode 100644 external/boringssl/fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7 create mode 100644 external/boringssl/fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5b create mode 100644 external/boringssl/fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3a create mode 100644 external/boringssl/fuzz/client_corpus/5e196581924d733f8faa3d3619453aa01e3700f3 create mode 100644 external/boringssl/fuzz/client_corpus/5e513e23df48329990ed63dc6310e820b21500fb create mode 100644 external/boringssl/fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6 create mode 100644 external/boringssl/fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331 create mode 100644 external/boringssl/fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28 create mode 100644 external/boringssl/fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925 create mode 100644 external/boringssl/fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5 create mode 100644 external/boringssl/fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabe create mode 100644 external/boringssl/fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34b create mode 100644 external/boringssl/fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4b create mode 100644 external/boringssl/fuzz/client_corpus/61e69397b08eef12ef32859936989b57525f163e create mode 100644 external/boringssl/fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c create mode 100644 external/boringssl/fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03 create mode 100644 external/boringssl/fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418 create mode 100644 external/boringssl/fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08 create mode 100644 external/boringssl/fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343 create mode 100644 external/boringssl/fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56 create mode 100644 external/boringssl/fuzz/client_corpus/62b7b6dde6cac1830d8d1b64c3ff146cc9ee909c create mode 100644 external/boringssl/fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a create mode 100644 external/boringssl/fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6 create mode 100644 external/boringssl/fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6 create mode 100644 external/boringssl/fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9 create mode 100644 external/boringssl/fuzz/client_corpus/650d6182ce2b79795477071a5edf71e5e4a2d9af create mode 100644 external/boringssl/fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341a create mode 100644 external/boringssl/fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7d create mode 100644 external/boringssl/fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caa create mode 100644 external/boringssl/fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561 create mode 100644 external/boringssl/fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851a create mode 100644 external/boringssl/fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153a create mode 100644 external/boringssl/fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6b create mode 100644 external/boringssl/fuzz/client_corpus/66ea20db9af412114e60b20143b063643ac0209f create mode 100644 external/boringssl/fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613 create mode 100644 external/boringssl/fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2 create mode 100644 external/boringssl/fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545 create mode 100644 external/boringssl/fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12 create mode 100644 external/boringssl/fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80 create mode 100644 external/boringssl/fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11b create mode 100644 external/boringssl/fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62 create mode 100644 external/boringssl/fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277 create mode 100644 external/boringssl/fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262 create mode 100644 external/boringssl/fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbd create mode 100644 external/boringssl/fuzz/client_corpus/695cb65aafb76161e3a319c68d4430ee80985b81 create mode 100644 external/boringssl/fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960a create mode 100644 external/boringssl/fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045 create mode 100644 external/boringssl/fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecf create mode 100644 external/boringssl/fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822 create mode 100644 external/boringssl/fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312 create mode 100644 external/boringssl/fuzz/client_corpus/6adf7477d929629afb4d07b4518a0e23b301b232 create mode 100644 external/boringssl/fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2e create mode 100644 external/boringssl/fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463b create mode 100644 external/boringssl/fuzz/client_corpus/6c55036b8922e6b076ca36b92afa11601625e5af create mode 100644 external/boringssl/fuzz/client_corpus/6c630175c87c742ab0c8723f6a0a53aae43b974e create mode 100644 external/boringssl/fuzz/client_corpus/6c651672e43ef4440abd90b3e6e1dd0a32e97437 create mode 100644 external/boringssl/fuzz/client_corpus/6cb141671c7744c225aa3f7ce0e9813ae01f2a2b create mode 100644 external/boringssl/fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363df create mode 100644 external/boringssl/fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5a create mode 100644 external/boringssl/fuzz/client_corpus/6d6212a5e12e69903e45291526bc0ecd3ea0e6f5 create mode 100644 external/boringssl/fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcad create mode 100644 external/boringssl/fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eec create mode 100644 external/boringssl/fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771 create mode 100644 external/boringssl/fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7 create mode 100644 external/boringssl/fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5 create mode 100644 external/boringssl/fuzz/client_corpus/71050f1658866c73590296856c498f54087519cc create mode 100644 external/boringssl/fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864 create mode 100644 external/boringssl/fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4a create mode 100644 external/boringssl/fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388 create mode 100644 external/boringssl/fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1 create mode 100644 external/boringssl/fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7 create mode 100644 external/boringssl/fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066 create mode 100644 external/boringssl/fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2 create mode 100644 external/boringssl/fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4 create mode 100644 external/boringssl/fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14b create mode 100644 external/boringssl/fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5 create mode 100644 external/boringssl/fuzz/client_corpus/73f63d7db6fb57a25e5f47a004e6f24eb66e685e create mode 100644 external/boringssl/fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0 create mode 100644 external/boringssl/fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6c create mode 100644 external/boringssl/fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43 create mode 100644 external/boringssl/fuzz/client_corpus/7492e1899d22a15452e163881437a23ccc705d45 create mode 100644 external/boringssl/fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4 create mode 100644 external/boringssl/fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20 create mode 100644 external/boringssl/fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24 create mode 100644 external/boringssl/fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186cc create mode 100644 external/boringssl/fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7 create mode 100644 external/boringssl/fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769 create mode 100644 external/boringssl/fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254 create mode 100644 external/boringssl/fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4 create mode 100644 external/boringssl/fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29 create mode 100644 external/boringssl/fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9 create mode 100644 external/boringssl/fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6 create mode 100644 external/boringssl/fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088 create mode 100644 external/boringssl/fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef create mode 100644 external/boringssl/fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3 create mode 100644 external/boringssl/fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210b create mode 100644 external/boringssl/fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40 create mode 100644 external/boringssl/fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35 create mode 100644 external/boringssl/fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913 create mode 100644 external/boringssl/fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0 create mode 100644 external/boringssl/fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853b create mode 100644 external/boringssl/fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578 create mode 100644 external/boringssl/fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5d create mode 100644 external/boringssl/fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0 create mode 100644 external/boringssl/fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256 create mode 100644 external/boringssl/fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01e create mode 100644 external/boringssl/fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320d create mode 100644 external/boringssl/fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053 create mode 100644 external/boringssl/fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26 create mode 100644 external/boringssl/fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63 create mode 100644 external/boringssl/fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0 create mode 100644 external/boringssl/fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87ba create mode 100644 external/boringssl/fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044d create mode 100644 external/boringssl/fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817b create mode 100644 external/boringssl/fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1ea create mode 100644 external/boringssl/fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa create mode 100644 external/boringssl/fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca create mode 100644 external/boringssl/fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86 create mode 100644 external/boringssl/fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205 create mode 100644 external/boringssl/fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6 create mode 100644 external/boringssl/fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571 create mode 100644 external/boringssl/fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727 create mode 100644 external/boringssl/fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270 create mode 100644 external/boringssl/fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62 create mode 100644 external/boringssl/fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182d create mode 100644 external/boringssl/fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8 create mode 100644 external/boringssl/fuzz/client_corpus/822f3b140b0934e8e0263f1dd2c6f1527c06df1f create mode 100644 external/boringssl/fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116 create mode 100644 external/boringssl/fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741c create mode 100644 external/boringssl/fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3 create mode 100644 external/boringssl/fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1a create mode 100644 external/boringssl/fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0 create mode 100644 external/boringssl/fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86b create mode 100644 external/boringssl/fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1d create mode 100644 external/boringssl/fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206 create mode 100644 external/boringssl/fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5 create mode 100644 external/boringssl/fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658 create mode 100644 external/boringssl/fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3f create mode 100644 external/boringssl/fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3e create mode 100644 external/boringssl/fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3d create mode 100644 external/boringssl/fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624 create mode 100644 external/boringssl/fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832 create mode 100644 external/boringssl/fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5 create mode 100644 external/boringssl/fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1e create mode 100644 external/boringssl/fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8 create mode 100644 external/boringssl/fuzz/client_corpus/89ce5fb7b86ce8f2c0e62b8fe79b12f9d2def007 create mode 100644 external/boringssl/fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078 create mode 100644 external/boringssl/fuzz/client_corpus/8a01471d4ddb4d5c1c71f89bb0018e9eb0aed463 create mode 100644 external/boringssl/fuzz/client_corpus/8a962b1da16fd4b7af2bd08d0a1421bdcc3306fe create mode 100644 external/boringssl/fuzz/client_corpus/8ae0eed9ec461f1b6cfa172573d0ff0c94d62f58 create mode 100644 external/boringssl/fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4 create mode 100644 external/boringssl/fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22 create mode 100644 external/boringssl/fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6 create mode 100644 external/boringssl/fuzz/client_corpus/8bb94ac9d58ce60fb4baab8403722f1a173497b3 create mode 100644 external/boringssl/fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93beb create mode 100644 external/boringssl/fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3 create mode 100644 external/boringssl/fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57 create mode 100644 external/boringssl/fuzz/client_corpus/8d3d73f19d7bdfdcf299934f0c865d14fd0a209b create mode 100644 external/boringssl/fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20 create mode 100644 external/boringssl/fuzz/client_corpus/8d5bca4e95a1b5f22533a680142064237957363d create mode 100644 external/boringssl/fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4d create mode 100644 external/boringssl/fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3 create mode 100644 external/boringssl/fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8 create mode 100644 external/boringssl/fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708f create mode 100644 external/boringssl/fuzz/client_corpus/8e3d1f50587b38d1b71c64cd1f047c4617ebea63 create mode 100644 external/boringssl/fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05 create mode 100644 external/boringssl/fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400 create mode 100644 external/boringssl/fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6 create mode 100644 external/boringssl/fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59 create mode 100644 external/boringssl/fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8b create mode 100644 external/boringssl/fuzz/client_corpus/90c6b18f6c5042404ad9bd8a44dc7f3d079d3f97 create mode 100644 external/boringssl/fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760 create mode 100644 external/boringssl/fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73 create mode 100644 external/boringssl/fuzz/client_corpus/919751352435a91c9e331722b0deb8b5a953eb17 create mode 100644 external/boringssl/fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3 create mode 100644 external/boringssl/fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674 create mode 100644 external/boringssl/fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92 create mode 100644 external/boringssl/fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783c create mode 100644 external/boringssl/fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141 create mode 100644 external/boringssl/fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488 create mode 100644 external/boringssl/fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc create mode 100644 external/boringssl/fuzz/client_corpus/93a0fefc5de9feda0a6e7130aea669a423920b9f create mode 100644 external/boringssl/fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d create mode 100644 external/boringssl/fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3a create mode 100644 external/boringssl/fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253 create mode 100644 external/boringssl/fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2c create mode 100644 external/boringssl/fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90d create mode 100644 external/boringssl/fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4b create mode 100644 external/boringssl/fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510b create mode 100644 external/boringssl/fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76 create mode 100644 external/boringssl/fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71 create mode 100644 external/boringssl/fuzz/client_corpus/96d52303f3d71a4b80cd05cbcfeb0de94cdff14e create mode 100644 external/boringssl/fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7 create mode 100644 external/boringssl/fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731 create mode 100644 external/boringssl/fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25d create mode 100644 external/boringssl/fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0 create mode 100644 external/boringssl/fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cf create mode 100644 external/boringssl/fuzz/client_corpus/99e5f2d8823aff6c698ecd0a2e0bf2a23f6f9f7e create mode 100644 external/boringssl/fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634 create mode 100644 external/boringssl/fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3 create mode 100644 external/boringssl/fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98d create mode 100644 external/boringssl/fuzz/client_corpus/9d66badf189ceb88b4a45d225c63a54787b9916e create mode 100644 external/boringssl/fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2 create mode 100644 external/boringssl/fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22 create mode 100644 external/boringssl/fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98d create mode 100644 external/boringssl/fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834 create mode 100644 external/boringssl/fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdc create mode 100644 external/boringssl/fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229 create mode 100644 external/boringssl/fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0 create mode 100644 external/boringssl/fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1 create mode 100644 external/boringssl/fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9 create mode 100644 external/boringssl/fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179 create mode 100644 external/boringssl/fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862daf create mode 100644 external/boringssl/fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0 create mode 100644 external/boringssl/fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486 create mode 100644 external/boringssl/fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261ad create mode 100644 external/boringssl/fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552 create mode 100644 external/boringssl/fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3 create mode 100644 external/boringssl/fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bb create mode 100644 external/boringssl/fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605b create mode 100644 external/boringssl/fuzz/client_corpus/a3bfeed2ef700425f8faf0c6b93295149f23ac2a create mode 100644 external/boringssl/fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104 create mode 100644 external/boringssl/fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928 create mode 100644 external/boringssl/fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20 create mode 100644 external/boringssl/fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3b create mode 100644 external/boringssl/fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401d create mode 100644 external/boringssl/fuzz/client_corpus/a5c7daa6ba53a703f416d7f258ceb73a0697fbfb create mode 100644 external/boringssl/fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821a create mode 100644 external/boringssl/fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290 create mode 100644 external/boringssl/fuzz/client_corpus/a6718d2e96c00ab472bab71e57b6ac3486b15921 create mode 100644 external/boringssl/fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdef create mode 100644 external/boringssl/fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826 create mode 100644 external/boringssl/fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305 create mode 100644 external/boringssl/fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769 create mode 100644 external/boringssl/fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94 create mode 100644 external/boringssl/fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28 create mode 100644 external/boringssl/fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42e create mode 100644 external/boringssl/fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641 create mode 100644 external/boringssl/fuzz/client_corpus/a867840096cb79e3ce2a5d9484ce84f9477e3201 create mode 100644 external/boringssl/fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98 create mode 100644 external/boringssl/fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973 create mode 100644 external/boringssl/fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53 create mode 100644 external/boringssl/fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7 create mode 100644 external/boringssl/fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6 create mode 100644 external/boringssl/fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585 create mode 100644 external/boringssl/fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6 create mode 100644 external/boringssl/fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71 create mode 100644 external/boringssl/fuzz/client_corpus/ac7d3c35fcfcfb6a3d02c4fc08f60981cb121664 create mode 100644 external/boringssl/fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508 create mode 100644 external/boringssl/fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5 create mode 100644 external/boringssl/fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60 create mode 100644 external/boringssl/fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872 create mode 100644 external/boringssl/fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5 create mode 100644 external/boringssl/fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807f create mode 100644 external/boringssl/fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683a create mode 100644 external/boringssl/fuzz/client_corpus/adc8f85e6d26d1d01ec10aa01b8733ec7622c7fd create mode 100644 external/boringssl/fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445 create mode 100644 external/boringssl/fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055 create mode 100644 external/boringssl/fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970 create mode 100644 external/boringssl/fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6 create mode 100644 external/boringssl/fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9 create mode 100644 external/boringssl/fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84 create mode 100644 external/boringssl/fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6 create mode 100644 external/boringssl/fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817 create mode 100644 external/boringssl/fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52 create mode 100644 external/boringssl/fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8a create mode 100644 external/boringssl/fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79 create mode 100644 external/boringssl/fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564 create mode 100644 external/boringssl/fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811 create mode 100644 external/boringssl/fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18 create mode 100644 external/boringssl/fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6 create mode 100644 external/boringssl/fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8 create mode 100644 external/boringssl/fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648 create mode 100644 external/boringssl/fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74f create mode 100644 external/boringssl/fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713be create mode 100644 external/boringssl/fuzz/client_corpus/b4d11620cbd84d8f68d387969c7e1b6db5b437f9 create mode 100644 external/boringssl/fuzz/client_corpus/b50f8d1d0d99c5d7c8b8b185aef00d3fb082c567 create mode 100644 external/boringssl/fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27d create mode 100644 external/boringssl/fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226 create mode 100644 external/boringssl/fuzz/client_corpus/b5709d7b4b2591636f8d80695dbf7b6a03ce488a create mode 100644 external/boringssl/fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621 create mode 100644 external/boringssl/fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18 create mode 100644 external/boringssl/fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941a create mode 100644 external/boringssl/fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1 create mode 100644 external/boringssl/fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfde create mode 100644 external/boringssl/fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9 create mode 100644 external/boringssl/fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43b create mode 100644 external/boringssl/fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fc create mode 100644 external/boringssl/fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683ae create mode 100644 external/boringssl/fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07a create mode 100644 external/boringssl/fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9b create mode 100644 external/boringssl/fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2 create mode 100644 external/boringssl/fuzz/client_corpus/b8ab490b280bfa2e0514a86776e7c2d069e26fc1 create mode 100644 external/boringssl/fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251b create mode 100644 external/boringssl/fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5 create mode 100644 external/boringssl/fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828 create mode 100644 external/boringssl/fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6 create mode 100644 external/boringssl/fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7 create mode 100644 external/boringssl/fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c create mode 100644 external/boringssl/fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246 create mode 100644 external/boringssl/fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55 create mode 100644 external/boringssl/fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4 create mode 100644 external/boringssl/fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29 create mode 100644 external/boringssl/fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730 create mode 100644 external/boringssl/fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4 create mode 100644 external/boringssl/fuzz/client_corpus/bd011a83422f5d64081ea5c6c9caf1224292ad42 create mode 100644 external/boringssl/fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0 create mode 100644 external/boringssl/fuzz/client_corpus/bd5f333b42d9e02433074109af2ed85120648125 create mode 100644 external/boringssl/fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c create mode 100644 external/boringssl/fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0ed create mode 100644 external/boringssl/fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0 create mode 100644 external/boringssl/fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98ea create mode 100644 external/boringssl/fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583 create mode 100644 external/boringssl/fuzz/client_corpus/c03fbdfcb8e959099df158b38e16e6e98fa0a8f1 create mode 100644 external/boringssl/fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8c create mode 100644 external/boringssl/fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4d create mode 100644 external/boringssl/fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8 create mode 100644 external/boringssl/fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427e create mode 100644 external/boringssl/fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86 create mode 100644 external/boringssl/fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8d create mode 100644 external/boringssl/fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523 create mode 100644 external/boringssl/fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419 create mode 100644 external/boringssl/fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9 create mode 100644 external/boringssl/fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224 create mode 100644 external/boringssl/fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862 create mode 100644 external/boringssl/fuzz/client_corpus/c588d48045128b1d22de91bb640411cfaa4bc9ad create mode 100644 external/boringssl/fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117 create mode 100644 external/boringssl/fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8 create mode 100644 external/boringssl/fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7 create mode 100644 external/boringssl/fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cb create mode 100644 external/boringssl/fuzz/client_corpus/c78af7af9a7f67ab59e314cfe67ca7825d697705 create mode 100644 external/boringssl/fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7 create mode 100644 external/boringssl/fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490b create mode 100644 external/boringssl/fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89 create mode 100644 external/boringssl/fuzz/client_corpus/c915f6eb5bf85d6f906722e77e4ec28493ed54d2 create mode 100644 external/boringssl/fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0 create mode 100644 external/boringssl/fuzz/client_corpus/c9ff9d69ff63ca545ec8ac2585c3c5202c2e552e create mode 100644 external/boringssl/fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7 create mode 100644 external/boringssl/fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152 create mode 100644 external/boringssl/fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5c create mode 100644 external/boringssl/fuzz/client_corpus/cbab437e9479b87d3cc898a5db555d5cca59db3b create mode 100644 external/boringssl/fuzz/client_corpus/cbc503f6dd40fdc5f03e8a90044cf183a595600a create mode 100644 external/boringssl/fuzz/client_corpus/cc3c09cc41156962a002569cc7467bf10ef77721 create mode 100644 external/boringssl/fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48 create mode 100644 external/boringssl/fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81 create mode 100644 external/boringssl/fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2 create mode 100644 external/boringssl/fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984 create mode 100644 external/boringssl/fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41 create mode 100644 external/boringssl/fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565d create mode 100644 external/boringssl/fuzz/client_corpus/cea198948bc4ad0e2eeaf2ccf116d53c0c577881 create mode 100644 external/boringssl/fuzz/client_corpus/cea7fd28eef6a02a13ea90d784c1207dded60b92 create mode 100644 external/boringssl/fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41 create mode 100644 external/boringssl/fuzz/client_corpus/cf6f67c363efa2d77cdc6b81f6e74c9fc3e17143 create mode 100644 external/boringssl/fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60 create mode 100644 external/boringssl/fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824b create mode 100644 external/boringssl/fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84 create mode 100644 external/boringssl/fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290 create mode 100644 external/boringssl/fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00f create mode 100644 external/boringssl/fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344 create mode 100644 external/boringssl/fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04 create mode 100644 external/boringssl/fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90 create mode 100644 external/boringssl/fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6 create mode 100644 external/boringssl/fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6d create mode 100644 external/boringssl/fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024 create mode 100644 external/boringssl/fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032 create mode 100644 external/boringssl/fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19 create mode 100644 external/boringssl/fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005 create mode 100644 external/boringssl/fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603 create mode 100644 external/boringssl/fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69 create mode 100644 external/boringssl/fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694 create mode 100644 external/boringssl/fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317a create mode 100644 external/boringssl/fuzz/client_corpus/d5149852f264e96d3a7bfb87aeacf88e21d7cd81 create mode 100644 external/boringssl/fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7 create mode 100644 external/boringssl/fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52 create mode 100644 external/boringssl/fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57c create mode 100644 external/boringssl/fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7 create mode 100644 external/boringssl/fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01 create mode 100644 external/boringssl/fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0 create mode 100644 external/boringssl/fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278 create mode 100644 external/boringssl/fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02 create mode 100644 external/boringssl/fuzz/client_corpus/d61f9163c366f3cb907570af9263cfe139523275 create mode 100644 external/boringssl/fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4 create mode 100644 external/boringssl/fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399 create mode 100644 external/boringssl/fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10 create mode 100644 external/boringssl/fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318 create mode 100644 external/boringssl/fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3b create mode 100644 external/boringssl/fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b create mode 100644 external/boringssl/fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5 create mode 100644 external/boringssl/fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4e create mode 100644 external/boringssl/fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559d create mode 100644 external/boringssl/fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93d create mode 100644 external/boringssl/fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bd create mode 100644 external/boringssl/fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9 create mode 100644 external/boringssl/fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0 create mode 100644 external/boringssl/fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575f create mode 100644 external/boringssl/fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d create mode 100644 external/boringssl/fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30 create mode 100644 external/boringssl/fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9 create mode 100644 external/boringssl/fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177aba create mode 100644 external/boringssl/fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856a create mode 100644 external/boringssl/fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01 create mode 100644 external/boringssl/fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303 create mode 100644 external/boringssl/fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294 create mode 100644 external/boringssl/fuzz/client_corpus/df314bab00b12c1a31e29132d5eb9771ba14edc8 create mode 100644 external/boringssl/fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0 create mode 100644 external/boringssl/fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0 create mode 100644 external/boringssl/fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099 create mode 100644 external/boringssl/fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679 create mode 100644 external/boringssl/fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998 create mode 100644 external/boringssl/fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074 create mode 100644 external/boringssl/fuzz/client_corpus/dfe4cc06c05e43dbedb195bd5b3e5d2cc889ab1e create mode 100644 external/boringssl/fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7d create mode 100644 external/boringssl/fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6 create mode 100644 external/boringssl/fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8 create mode 100644 external/boringssl/fuzz/client_corpus/e1fc2e3105fc3a2a7be7d48d8edce0632572a88b create mode 100644 external/boringssl/fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305 create mode 100644 external/boringssl/fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897 create mode 100644 external/boringssl/fuzz/client_corpus/e31c99618df1f322012029dcc2e0f1d4fd4c3977 create mode 100644 external/boringssl/fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ec create mode 100644 external/boringssl/fuzz/client_corpus/e3f7aeef652e35f920ed3fb6081884f12c9f9bcd create mode 100644 external/boringssl/fuzz/client_corpus/e41056775fb1db9c520347187e5f33b529db14cb create mode 100644 external/boringssl/fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4e create mode 100644 external/boringssl/fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0 create mode 100644 external/boringssl/fuzz/client_corpus/e48eb2509e260ee8d19ebc618b895a457491c583 create mode 100644 external/boringssl/fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8 create mode 100644 external/boringssl/fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501 create mode 100644 external/boringssl/fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eeb create mode 100644 external/boringssl/fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111 create mode 100644 external/boringssl/fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07d create mode 100644 external/boringssl/fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444 create mode 100644 external/boringssl/fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6a create mode 100644 external/boringssl/fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875 create mode 100644 external/boringssl/fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0fea create mode 100644 external/boringssl/fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966ac create mode 100644 external/boringssl/fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478 create mode 100644 external/boringssl/fuzz/client_corpus/e88137978a989ffac6c11e5565b1678e3a2f2a07 create mode 100644 external/boringssl/fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26b create mode 100644 external/boringssl/fuzz/client_corpus/ea76c818a4ae9c92d431de82f50c194727e99d9c create mode 100644 external/boringssl/fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90ad create mode 100644 external/boringssl/fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670 create mode 100644 external/boringssl/fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884 create mode 100644 external/boringssl/fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1 create mode 100644 external/boringssl/fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84 create mode 100644 external/boringssl/fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2 create mode 100644 external/boringssl/fuzz/client_corpus/eda54f7e9fa02af74383bb89950adf6dc3d55401 create mode 100644 external/boringssl/fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6 create mode 100644 external/boringssl/fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190 create mode 100644 external/boringssl/fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59 create mode 100644 external/boringssl/fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265ca create mode 100644 external/boringssl/fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2f create mode 100644 external/boringssl/fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786 create mode 100644 external/boringssl/fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1 create mode 100644 external/boringssl/fuzz/client_corpus/f044a49ce9380a26ab8ab4b92999c9d045fde573 create mode 100644 external/boringssl/fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5 create mode 100644 external/boringssl/fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35 create mode 100644 external/boringssl/fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1 create mode 100644 external/boringssl/fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3 create mode 100644 external/boringssl/fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0 create mode 100644 external/boringssl/fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16 create mode 100644 external/boringssl/fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2 create mode 100644 external/boringssl/fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0 create mode 100644 external/boringssl/fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286 create mode 100644 external/boringssl/fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2 create mode 100644 external/boringssl/fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9 create mode 100644 external/boringssl/fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8e create mode 100644 external/boringssl/fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097a create mode 100644 external/boringssl/fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8 create mode 100644 external/boringssl/fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944a create mode 100644 external/boringssl/fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae create mode 100644 external/boringssl/fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4b create mode 100644 external/boringssl/fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84fe create mode 100644 external/boringssl/fuzz/client_corpus/f7048f702c3ca6c9586dbb81db5bf4858dcda2f6 create mode 100644 external/boringssl/fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3 create mode 100644 external/boringssl/fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9 create mode 100644 external/boringssl/fuzz/client_corpus/f81cb544d394ef24caab41b1d9fc7108a95ceb1a create mode 100644 external/boringssl/fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060a create mode 100644 external/boringssl/fuzz/client_corpus/f99f314fc629fdbb8ef0abbfa2b1315f081c66aa create mode 100644 external/boringssl/fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090 create mode 100644 external/boringssl/fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21 create mode 100644 external/boringssl/fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502a create mode 100644 external/boringssl/fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31 create mode 100644 external/boringssl/fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08 create mode 100644 external/boringssl/fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80b create mode 100644 external/boringssl/fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afb create mode 100644 external/boringssl/fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5a create mode 100644 external/boringssl/fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579 create mode 100644 external/boringssl/fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60 create mode 100644 external/boringssl/fuzz/client_corpus/ff7ba21b79ba75d821d722933b5d03a1437c38f3 create mode 100644 external/boringssl/fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749 create mode 100644 external/boringssl/fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561 create mode 100644 external/boringssl/fuzz/minimise_corpuses.sh create mode 100644 external/boringssl/fuzz/pkcs8.cc create mode 100644 external/boringssl/fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350b create mode 100644 external/boringssl/fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3f create mode 100644 external/boringssl/fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125ab create mode 100644 external/boringssl/fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36b create mode 100644 external/boringssl/fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41fe create mode 100644 external/boringssl/fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648 create mode 100644 external/boringssl/fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18e create mode 100644 external/boringssl/fuzz/privkey.cc create mode 100644 external/boringssl/fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3 create mode 100644 external/boringssl/fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104 create mode 100644 external/boringssl/fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9 create mode 100644 external/boringssl/fuzz/privkey_corpus/040e09a6e89086dfd9260699f1dd27f1ac8fc608 create mode 100644 external/boringssl/fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67 create mode 100644 external/boringssl/fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4 create mode 100644 external/boringssl/fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35 create mode 100644 external/boringssl/fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2 create mode 100644 external/boringssl/fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60b create mode 100644 external/boringssl/fuzz/privkey_corpus/09a98dfe76a481a565719e05e80fd48d780144bf create mode 100644 external/boringssl/fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92f create mode 100644 external/boringssl/fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4f create mode 100644 external/boringssl/fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346 create mode 100644 external/boringssl/fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5 create mode 100644 external/boringssl/fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961 create mode 100644 external/boringssl/fuzz/privkey_corpus/0ce90fa3fde09714028bbed4b835b9889868f05b create mode 100644 external/boringssl/fuzz/privkey_corpus/0da750195873f5330d846c55736fa9c952daba74 create mode 100644 external/boringssl/fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95e create mode 100644 external/boringssl/fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2f create mode 100644 external/boringssl/fuzz/privkey_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff create mode 100644 external/boringssl/fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0 create mode 100644 external/boringssl/fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673 create mode 100644 external/boringssl/fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4 create mode 100644 external/boringssl/fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7 create mode 100644 external/boringssl/fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794 create mode 100644 external/boringssl/fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1 create mode 100644 external/boringssl/fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1 create mode 100644 external/boringssl/fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4 create mode 100644 external/boringssl/fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574 create mode 100644 external/boringssl/fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301b create mode 100644 external/boringssl/fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489d create mode 100644 external/boringssl/fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fd create mode 100644 external/boringssl/fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b create mode 100644 external/boringssl/fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018 create mode 100644 external/boringssl/fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01 create mode 100644 external/boringssl/fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73ef create mode 100644 external/boringssl/fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904 create mode 100644 external/boringssl/fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423b create mode 100644 external/boringssl/fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8 create mode 100644 external/boringssl/fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4 create mode 100644 external/boringssl/fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9 create mode 100644 external/boringssl/fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183e create mode 100644 external/boringssl/fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0 create mode 100644 external/boringssl/fuzz/privkey_corpus/2d4091ae2ed10fe2008a9345042316e0d9e12f78 create mode 100644 external/boringssl/fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696 create mode 100644 external/boringssl/fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9 create mode 100644 external/boringssl/fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274 create mode 100644 external/boringssl/fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9 create mode 100644 external/boringssl/fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164 create mode 100644 external/boringssl/fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4 create mode 100644 external/boringssl/fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068 create mode 100644 external/boringssl/fuzz/privkey_corpus/32d0205dcae956ac26c7faa7a5696daaf288ac83 create mode 100644 external/boringssl/fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29 create mode 100644 external/boringssl/fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0 create mode 100644 external/boringssl/fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32af create mode 100644 external/boringssl/fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39 create mode 100644 external/boringssl/fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75 create mode 100644 external/boringssl/fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19ef create mode 100644 external/boringssl/fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adf create mode 100644 external/boringssl/fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735 create mode 100644 external/boringssl/fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85 create mode 100644 external/boringssl/fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4 create mode 100644 external/boringssl/fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7 create mode 100644 external/boringssl/fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512 create mode 100644 external/boringssl/fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754 create mode 100644 external/boringssl/fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193 create mode 100644 external/boringssl/fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31 create mode 100644 external/boringssl/fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574b create mode 100644 external/boringssl/fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10 create mode 100644 external/boringssl/fuzz/privkey_corpus/408eb93771f2db1955f2d3b886aa1288955e9595 create mode 100644 external/boringssl/fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217 create mode 100644 external/boringssl/fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5 create mode 100644 external/boringssl/fuzz/privkey_corpus/435a4c85a2ac1876353838fa2a6ed505b0513fb6 create mode 100644 external/boringssl/fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0 create mode 100644 external/boringssl/fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412 create mode 100644 external/boringssl/fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db create mode 100644 external/boringssl/fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04 create mode 100644 external/boringssl/fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28 create mode 100644 external/boringssl/fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647 create mode 100644 external/boringssl/fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4e create mode 100644 external/boringssl/fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8 create mode 100644 external/boringssl/fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13e create mode 100644 external/boringssl/fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040 create mode 100644 external/boringssl/fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0 create mode 100644 external/boringssl/fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6c create mode 100644 external/boringssl/fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9 create mode 100644 external/boringssl/fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287 create mode 100644 external/boringssl/fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87 create mode 100644 external/boringssl/fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36 create mode 100644 external/boringssl/fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9 create mode 100644 external/boringssl/fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217 create mode 100644 external/boringssl/fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692d create mode 100644 external/boringssl/fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e create mode 100644 external/boringssl/fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e create mode 100644 external/boringssl/fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841 create mode 100644 external/boringssl/fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaa create mode 100644 external/boringssl/fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050b create mode 100644 external/boringssl/fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60bec create mode 100644 external/boringssl/fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c create mode 100644 external/boringssl/fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8 create mode 100644 external/boringssl/fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cb create mode 100644 external/boringssl/fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9 create mode 100644 external/boringssl/fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9b create mode 100644 external/boringssl/fuzz/privkey_corpus/63fcd39ff8f3d87e84282915540cbf08e2df0d7d create mode 100644 external/boringssl/fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658 create mode 100644 external/boringssl/fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3 create mode 100644 external/boringssl/fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67 create mode 100644 external/boringssl/fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965 create mode 100644 external/boringssl/fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308 create mode 100644 external/boringssl/fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884b create mode 100644 external/boringssl/fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1 create mode 100644 external/boringssl/fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606d create mode 100644 external/boringssl/fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0b create mode 100644 external/boringssl/fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9b create mode 100644 external/boringssl/fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ec create mode 100644 external/boringssl/fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0b create mode 100644 external/boringssl/fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14 create mode 100644 external/boringssl/fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3 create mode 100644 external/boringssl/fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10 create mode 100644 external/boringssl/fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7 create mode 100644 external/boringssl/fuzz/privkey_corpus/7508d58d4f00dc14a072ef68c79d5db942195bac create mode 100644 external/boringssl/fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72ea create mode 100644 external/boringssl/fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ec create mode 100644 external/boringssl/fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2f create mode 100644 external/boringssl/fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86 create mode 100644 external/boringssl/fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26b create mode 100644 external/boringssl/fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70 create mode 100644 external/boringssl/fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462e create mode 100644 external/boringssl/fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bdd create mode 100644 external/boringssl/fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158 create mode 100644 external/boringssl/fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018 create mode 100644 external/boringssl/fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90 create mode 100644 external/boringssl/fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856 create mode 100644 external/boringssl/fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270 create mode 100644 external/boringssl/fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892 create mode 100644 external/boringssl/fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491b create mode 100644 external/boringssl/fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fc create mode 100644 external/boringssl/fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bb create mode 100644 external/boringssl/fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eef create mode 100644 external/boringssl/fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688 create mode 100644 external/boringssl/fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0 create mode 100644 external/boringssl/fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009 create mode 100644 external/boringssl/fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99d create mode 100644 external/boringssl/fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876c create mode 100644 external/boringssl/fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5 create mode 100644 external/boringssl/fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9 create mode 100644 external/boringssl/fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2c create mode 100644 external/boringssl/fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0 create mode 100644 external/boringssl/fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365 create mode 100644 external/boringssl/fuzz/privkey_corpus/88053e0d269f3cb40b00c68ef2ee4e51aab1b669 create mode 100644 external/boringssl/fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088 create mode 100644 external/boringssl/fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3 create mode 100644 external/boringssl/fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347d create mode 100644 external/boringssl/fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14c create mode 100644 external/boringssl/fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206 create mode 100644 external/boringssl/fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1e create mode 100644 external/boringssl/fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4 create mode 100644 external/boringssl/fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15 create mode 100644 external/boringssl/fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afa create mode 100644 external/boringssl/fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3 create mode 100644 external/boringssl/fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594 create mode 100644 external/boringssl/fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354 create mode 100644 external/boringssl/fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23 create mode 100644 external/boringssl/fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88 create mode 100644 external/boringssl/fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9 create mode 100644 external/boringssl/fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931f create mode 100644 external/boringssl/fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49 create mode 100644 external/boringssl/fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02 create mode 100644 external/boringssl/fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6ca create mode 100644 external/boringssl/fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631 create mode 100644 external/boringssl/fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cf create mode 100644 external/boringssl/fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dac create mode 100644 external/boringssl/fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0c create mode 100644 external/boringssl/fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546 create mode 100644 external/boringssl/fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4 create mode 100644 external/boringssl/fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12c create mode 100644 external/boringssl/fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425 create mode 100644 external/boringssl/fuzz/privkey_corpus/9f1eabfff336e298505550b3f369c61431289713 create mode 100644 external/boringssl/fuzz/privkey_corpus/9f24c5b2bf1b8306de8f5f708476773bfdf8d141 create mode 100644 external/boringssl/fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766ed create mode 100644 external/boringssl/fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7 create mode 100644 external/boringssl/fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0df create mode 100644 external/boringssl/fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfb create mode 100644 external/boringssl/fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966bee create mode 100644 external/boringssl/fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555 create mode 100644 external/boringssl/fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2d create mode 100644 external/boringssl/fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5 create mode 100644 external/boringssl/fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078 create mode 100644 external/boringssl/fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43a create mode 100644 external/boringssl/fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042 create mode 100644 external/boringssl/fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6 create mode 100644 external/boringssl/fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fad create mode 100644 external/boringssl/fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4d create mode 100644 external/boringssl/fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82 create mode 100644 external/boringssl/fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544 create mode 100644 external/boringssl/fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908 create mode 100644 external/boringssl/fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534e create mode 100644 external/boringssl/fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4 create mode 100644 external/boringssl/fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bf create mode 100644 external/boringssl/fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451 create mode 100644 external/boringssl/fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d create mode 100644 external/boringssl/fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238 create mode 100644 external/boringssl/fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321 create mode 100644 external/boringssl/fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898c create mode 100644 external/boringssl/fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636 create mode 100644 external/boringssl/fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185 create mode 100644 external/boringssl/fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6 create mode 100644 external/boringssl/fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4 create mode 100644 external/boringssl/fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4 create mode 100644 external/boringssl/fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3 create mode 100644 external/boringssl/fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfca create mode 100644 external/boringssl/fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369 create mode 100644 external/boringssl/fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711e create mode 100644 external/boringssl/fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273 create mode 100644 external/boringssl/fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064f create mode 100644 external/boringssl/fuzz/privkey_corpus/beca0cd7b91a6b0af4fc012cf1385952287660af create mode 100644 external/boringssl/fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591ee create mode 100644 external/boringssl/fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188f create mode 100644 external/boringssl/fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b create mode 100644 external/boringssl/fuzz/privkey_corpus/c1a97da39a236c416de37437ac41ab4ff86caee8 create mode 100644 external/boringssl/fuzz/privkey_corpus/c24ffe679d844cc26ac590f2657bd36de7876703 create mode 100644 external/boringssl/fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caece create mode 100644 external/boringssl/fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216 create mode 100644 external/boringssl/fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050 create mode 100644 external/boringssl/fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3 create mode 100644 external/boringssl/fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71 create mode 100644 external/boringssl/fuzz/privkey_corpus/c7639de8641dc12f675107b0ce6aee03e1f4ca46 create mode 100644 external/boringssl/fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75 create mode 100644 external/boringssl/fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7b create mode 100644 external/boringssl/fuzz/privkey_corpus/ca3805fce726847a1fcd57e100bde2c4058afa6e create mode 100644 external/boringssl/fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2b create mode 100644 external/boringssl/fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19 create mode 100644 external/boringssl/fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acf create mode 100644 external/boringssl/fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21 create mode 100644 external/boringssl/fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016 create mode 100644 external/boringssl/fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62 create mode 100644 external/boringssl/fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643 create mode 100644 external/boringssl/fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99 create mode 100644 external/boringssl/fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5 create mode 100644 external/boringssl/fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1 create mode 100644 external/boringssl/fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedb create mode 100644 external/boringssl/fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2b create mode 100644 external/boringssl/fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32 create mode 100644 external/boringssl/fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec create mode 100644 external/boringssl/fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35 create mode 100644 external/boringssl/fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0 create mode 100644 external/boringssl/fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28 create mode 100644 external/boringssl/fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375 create mode 100644 external/boringssl/fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44 create mode 100644 external/boringssl/fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112 create mode 100644 external/boringssl/fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7 create mode 100644 external/boringssl/fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2 create mode 100644 external/boringssl/fuzz/privkey_corpus/dcd1e294bde4644814fcce9efae0302f7eb0238a create mode 100644 external/boringssl/fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fd create mode 100644 external/boringssl/fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151 create mode 100644 external/boringssl/fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041 create mode 100644 external/boringssl/fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7 create mode 100644 external/boringssl/fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091 create mode 100644 external/boringssl/fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798d create mode 100644 external/boringssl/fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54 create mode 100644 external/boringssl/fuzz/privkey_corpus/e37e78da0ab0693a777912980c4db4e9a8faa975 create mode 100644 external/boringssl/fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10 create mode 100644 external/boringssl/fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36d create mode 100644 external/boringssl/fuzz/privkey_corpus/e5c82c5fcbe0067ffda8defedc3ce3a7fc1e0ce9 create mode 100644 external/boringssl/fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5 create mode 100644 external/boringssl/fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660c create mode 100644 external/boringssl/fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0ad create mode 100644 external/boringssl/fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464 create mode 100644 external/boringssl/fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dc create mode 100644 external/boringssl/fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7 create mode 100644 external/boringssl/fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41 create mode 100644 external/boringssl/fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477 create mode 100644 external/boringssl/fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94 create mode 100644 external/boringssl/fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424 create mode 100644 external/boringssl/fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7 create mode 100644 external/boringssl/fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400d create mode 100644 external/boringssl/fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96 create mode 100644 external/boringssl/fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8 create mode 100644 external/boringssl/fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9ed create mode 100644 external/boringssl/fuzz/privkey_corpus/f195c020a28dfc5f2fb6af256b524ddcd93756ed create mode 100644 external/boringssl/fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61d create mode 100644 external/boringssl/fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076b create mode 100644 external/boringssl/fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162d create mode 100644 external/boringssl/fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985e create mode 100644 external/boringssl/fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34b create mode 100644 external/boringssl/fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bd create mode 100644 external/boringssl/fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bd create mode 100644 external/boringssl/fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7 create mode 100644 external/boringssl/fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634e create mode 100644 external/boringssl/fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e create mode 100644 external/boringssl/fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848a create mode 100644 external/boringssl/fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7ce create mode 100644 external/boringssl/fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420d create mode 100644 external/boringssl/fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5e create mode 100644 external/boringssl/fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208 create mode 100644 external/boringssl/fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4 create mode 100644 external/boringssl/fuzz/read_pem.cc create mode 100644 external/boringssl/fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e2 create mode 100644 external/boringssl/fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d create mode 100644 external/boringssl/fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3 create mode 100644 external/boringssl/fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e create mode 100644 external/boringssl/fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0 create mode 100644 external/boringssl/fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f4 create mode 100644 external/boringssl/fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a create mode 100644 external/boringssl/fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237d create mode 100644 external/boringssl/fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f create mode 100644 external/boringssl/fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e1 create mode 100644 external/boringssl/fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc32 create mode 100644 external/boringssl/fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e8 create mode 100644 external/boringssl/fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5 create mode 100644 external/boringssl/fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67 create mode 100644 external/boringssl/fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4 create mode 100644 external/boringssl/fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe52789 create mode 100644 external/boringssl/fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8 create mode 100644 external/boringssl/fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933 create mode 100644 external/boringssl/fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3 create mode 100644 external/boringssl/fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f create mode 100644 external/boringssl/fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeed create mode 100644 external/boringssl/fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c111 create mode 100644 external/boringssl/fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f create mode 100644 external/boringssl/fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0 create mode 100644 external/boringssl/fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f13121 create mode 100644 external/boringssl/fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a create mode 100644 external/boringssl/fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef25 create mode 100644 external/boringssl/fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181 create mode 100644 external/boringssl/fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d798 create mode 100644 external/boringssl/fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2 create mode 100644 external/boringssl/fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18 create mode 100644 external/boringssl/fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64 create mode 100644 external/boringssl/fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb create mode 100644 external/boringssl/fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d create mode 100644 external/boringssl/fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588 create mode 100644 external/boringssl/fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e create mode 100644 external/boringssl/fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d45596 create mode 100644 external/boringssl/fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18 create mode 100644 external/boringssl/fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2 create mode 100644 external/boringssl/fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208c create mode 100644 external/boringssl/fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e8 create mode 100644 external/boringssl/fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55 create mode 100644 external/boringssl/fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96 create mode 100644 external/boringssl/fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e create mode 100644 external/boringssl/fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f4760 create mode 100644 external/boringssl/fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb68 create mode 100644 external/boringssl/fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d907 create mode 100644 external/boringssl/fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c create mode 100644 external/boringssl/fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2 create mode 100644 external/boringssl/fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b80 create mode 100644 external/boringssl/fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e6 create mode 100644 external/boringssl/fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa915 create mode 100644 external/boringssl/fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567 create mode 100644 external/boringssl/fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda create mode 100644 external/boringssl/fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b21126 create mode 100644 external/boringssl/fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70b create mode 100644 external/boringssl/fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e848121 create mode 100644 external/boringssl/fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f create mode 100644 external/boringssl/fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd create mode 100644 external/boringssl/fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232fe create mode 100644 external/boringssl/fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c create mode 100644 external/boringssl/fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5db create mode 100644 external/boringssl/fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b create mode 100644 external/boringssl/fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f37 create mode 100644 external/boringssl/fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad create mode 100644 external/boringssl/fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d3491 create mode 100644 external/boringssl/fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f create mode 100644 external/boringssl/fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e create mode 100644 external/boringssl/fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e785 create mode 100644 external/boringssl/fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1 create mode 100644 external/boringssl/fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33f create mode 100644 external/boringssl/fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6 create mode 100644 external/boringssl/fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f3 create mode 100644 external/boringssl/fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae711 create mode 100644 external/boringssl/fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5 create mode 100644 external/boringssl/fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158af create mode 100644 external/boringssl/fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca create mode 100644 external/boringssl/fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46 create mode 100644 external/boringssl/fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c create mode 100644 external/boringssl/fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad create mode 100644 external/boringssl/fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b create mode 100644 external/boringssl/fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009ce create mode 100644 external/boringssl/fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b9 create mode 100644 external/boringssl/fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c3990385 create mode 100644 external/boringssl/fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa513 create mode 100644 external/boringssl/fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5c create mode 100644 external/boringssl/fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b9 create mode 100644 external/boringssl/fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf0 create mode 100644 external/boringssl/fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b71205 create mode 100644 external/boringssl/fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf347929 create mode 100644 external/boringssl/fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1 create mode 100644 external/boringssl/fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26a create mode 100644 external/boringssl/fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e1 create mode 100644 external/boringssl/fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e0 create mode 100644 external/boringssl/fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c create mode 100644 external/boringssl/fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89 create mode 100644 external/boringssl/fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5 create mode 100644 external/boringssl/fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214d create mode 100644 external/boringssl/fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a421 create mode 100644 external/boringssl/fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e create mode 100644 external/boringssl/fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695 create mode 100644 external/boringssl/fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce743 create mode 100644 external/boringssl/fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c create mode 100644 external/boringssl/fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678f create mode 100644 external/boringssl/fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2c create mode 100644 external/boringssl/fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb create mode 100644 external/boringssl/fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb create mode 100644 external/boringssl/fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f8 create mode 100644 external/boringssl/fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6aca create mode 100644 external/boringssl/fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd5 create mode 100644 external/boringssl/fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e create mode 100644 external/boringssl/fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d058 create mode 100644 external/boringssl/fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fc create mode 100644 external/boringssl/fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e create mode 100644 external/boringssl/fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5 create mode 100644 external/boringssl/fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f create mode 100644 external/boringssl/fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f create mode 100644 external/boringssl/fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf create mode 100644 external/boringssl/fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded create mode 100644 external/boringssl/fuzz/server.cc create mode 100644 external/boringssl/fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49c create mode 100644 external/boringssl/fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9ab create mode 100644 external/boringssl/fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2b create mode 100644 external/boringssl/fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9 create mode 100644 external/boringssl/fuzz/server_corpus/0353776fd79d387026cfe5366f46f5a7417e58e2 create mode 100644 external/boringssl/fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480 create mode 100644 external/boringssl/fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27 create mode 100644 external/boringssl/fuzz/server_corpus/03ed4f1ff81afbad5eedbb5a80b56b23298ec078 create mode 100644 external/boringssl/fuzz/server_corpus/03fc9321fb45199b8fbbdefabc651e84b73f0ff8 create mode 100644 external/boringssl/fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d create mode 100644 external/boringssl/fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719c create mode 100644 external/boringssl/fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400e create mode 100644 external/boringssl/fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8fe create mode 100644 external/boringssl/fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6 create mode 100644 external/boringssl/fuzz/server_corpus/0729cde85be33f7f78ed90db14fc05924f755fc0 create mode 100644 external/boringssl/fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44 create mode 100644 external/boringssl/fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baa create mode 100644 external/boringssl/fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efe create mode 100644 external/boringssl/fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578f create mode 100644 external/boringssl/fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87ad create mode 100644 external/boringssl/fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785f create mode 100644 external/boringssl/fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c create mode 100644 external/boringssl/fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cf create mode 100644 external/boringssl/fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822 create mode 100644 external/boringssl/fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93a create mode 100644 external/boringssl/fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8 create mode 100644 external/boringssl/fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16 create mode 100644 external/boringssl/fuzz/server_corpus/10e8fb6fd26d9721bb6131d91281755ebf94ef21 create mode 100644 external/boringssl/fuzz/server_corpus/12a98036ff99402f5be27c4e64456059b440c248 create mode 100644 external/boringssl/fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906 create mode 100644 external/boringssl/fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1 create mode 100644 external/boringssl/fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546 create mode 100644 external/boringssl/fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489 create mode 100644 external/boringssl/fuzz/server_corpus/1584b2eb5bc2f0e9351f5630ba9f513ffe9c1089 create mode 100644 external/boringssl/fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdac create mode 100644 external/boringssl/fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4 create mode 100644 external/boringssl/fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659 create mode 100644 external/boringssl/fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506 create mode 100644 external/boringssl/fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39c create mode 100644 external/boringssl/fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffd create mode 100644 external/boringssl/fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97 create mode 100644 external/boringssl/fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33c create mode 100644 external/boringssl/fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3 create mode 100644 external/boringssl/fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0aff create mode 100644 external/boringssl/fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537 create mode 100644 external/boringssl/fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4 create mode 100644 external/boringssl/fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4d create mode 100644 external/boringssl/fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1 create mode 100644 external/boringssl/fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0 create mode 100644 external/boringssl/fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29 create mode 100644 external/boringssl/fuzz/server_corpus/260ef2d666d03e5451109135b50cbd9657fc6964 create mode 100644 external/boringssl/fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59b create mode 100644 external/boringssl/fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08c create mode 100644 external/boringssl/fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dff create mode 100644 external/boringssl/fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513a create mode 100644 external/boringssl/fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3 create mode 100644 external/boringssl/fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7 create mode 100644 external/boringssl/fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3 create mode 100644 external/boringssl/fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24 create mode 100644 external/boringssl/fuzz/server_corpus/298ee587ceb3e7685ab165fee56780031113c766 create mode 100644 external/boringssl/fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390 create mode 100644 external/boringssl/fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651 create mode 100644 external/boringssl/fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17 create mode 100644 external/boringssl/fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2a create mode 100644 external/boringssl/fuzz/server_corpus/2e830d13eff02a0da6b6ae20ca271cb8cdbdb64a create mode 100644 external/boringssl/fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41 create mode 100644 external/boringssl/fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508e create mode 100644 external/boringssl/fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7 create mode 100644 external/boringssl/fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dc create mode 100644 external/boringssl/fuzz/server_corpus/31fce22e8c242afcd1c122dd1623c77e0b1b4a0d create mode 100644 external/boringssl/fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3 create mode 100644 external/boringssl/fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768 create mode 100644 external/boringssl/fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6da create mode 100644 external/boringssl/fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9 create mode 100644 external/boringssl/fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9 create mode 100644 external/boringssl/fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43 create mode 100644 external/boringssl/fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7c create mode 100644 external/boringssl/fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206 create mode 100644 external/boringssl/fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3 create mode 100644 external/boringssl/fuzz/server_corpus/360b997587a9c6f4773e1ccc2f56a3e60d7d6b1c create mode 100644 external/boringssl/fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515d create mode 100644 external/boringssl/fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3 create mode 100644 external/boringssl/fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770 create mode 100644 external/boringssl/fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89 create mode 100644 external/boringssl/fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661 create mode 100644 external/boringssl/fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14 create mode 100644 external/boringssl/fuzz/server_corpus/3928f49b93a191a465e788af538a969278c14823 create mode 100644 external/boringssl/fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74b create mode 100644 external/boringssl/fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528 create mode 100644 external/boringssl/fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e create mode 100644 external/boringssl/fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2 create mode 100644 external/boringssl/fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1 create mode 100644 external/boringssl/fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843 create mode 100644 external/boringssl/fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294 create mode 100644 external/boringssl/fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884 create mode 100644 external/boringssl/fuzz/server_corpus/3e71382d2831304e50054a0175baf664fae49608 create mode 100644 external/boringssl/fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7 create mode 100644 external/boringssl/fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9 create mode 100644 external/boringssl/fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9 create mode 100644 external/boringssl/fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929 create mode 100644 external/boringssl/fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384 create mode 100644 external/boringssl/fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44 create mode 100644 external/boringssl/fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348 create mode 100644 external/boringssl/fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814 create mode 100644 external/boringssl/fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81 create mode 100644 external/boringssl/fuzz/server_corpus/458469682e541e27218f68140b3ec5e08a160907 create mode 100644 external/boringssl/fuzz/server_corpus/45c8ed787ce862a29bbef404b84fd672d4e44c02 create mode 100644 external/boringssl/fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550 create mode 100644 external/boringssl/fuzz/server_corpus/463b9a9c1edafa2d42b1b0dbd9390186002eb775 create mode 100644 external/boringssl/fuzz/server_corpus/480fdad19f48ccb66c79e4daad4bf4c189334d76 create mode 100644 external/boringssl/fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6 create mode 100644 external/boringssl/fuzz/server_corpus/499f80ae1a49f344f6ea00678211e0bc08339451 create mode 100644 external/boringssl/fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61 create mode 100644 external/boringssl/fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5 create mode 100644 external/boringssl/fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345 create mode 100644 external/boringssl/fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1 create mode 100644 external/boringssl/fuzz/server_corpus/4b8a432fa4bf47f45d9c2ed257f0a958fcc94f9c create mode 100644 external/boringssl/fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39be create mode 100644 external/boringssl/fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99dd create mode 100644 external/boringssl/fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110d create mode 100644 external/boringssl/fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caa create mode 100644 external/boringssl/fuzz/server_corpus/50edce6beb7be88fd0fec26d84bc2706432adccd create mode 100644 external/boringssl/fuzz/server_corpus/522d6829d952b1611ed141de5d2b500e95f46133 create mode 100644 external/boringssl/fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72 create mode 100644 external/boringssl/fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553 create mode 100644 external/boringssl/fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045 create mode 100644 external/boringssl/fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbf create mode 100644 external/boringssl/fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838 create mode 100644 external/boringssl/fuzz/server_corpus/5686ea1bd2b626e81ca079482a81c4133a589e0d create mode 100644 external/boringssl/fuzz/server_corpus/57779cd03374bd1ffb254ee0749d437108879a28 create mode 100644 external/boringssl/fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cd create mode 100644 external/boringssl/fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6 create mode 100644 external/boringssl/fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281 create mode 100644 external/boringssl/fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604 create mode 100644 external/boringssl/fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8 create mode 100644 external/boringssl/fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879 create mode 100644 external/boringssl/fuzz/server_corpus/5bef1a165880066972ce67fc28c01f46bc306e6b create mode 100644 external/boringssl/fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a create mode 100644 external/boringssl/fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adf create mode 100644 external/boringssl/fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0 create mode 100644 external/boringssl/fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8 create mode 100644 external/boringssl/fuzz/server_corpus/5f70e0ee2f616a7b4bbb743a9b1b91517bc3f057 create mode 100644 external/boringssl/fuzz/server_corpus/6040b1427656967d16ff771db3d32ecc5ec579f9 create mode 100644 external/boringssl/fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902 create mode 100644 external/boringssl/fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644e create mode 100644 external/boringssl/fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591f create mode 100644 external/boringssl/fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7ee create mode 100644 external/boringssl/fuzz/server_corpus/630800205061e44da8f2a98f73192b6c02ac2cda create mode 100644 external/boringssl/fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485 create mode 100644 external/boringssl/fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea create mode 100644 external/boringssl/fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3 create mode 100644 external/boringssl/fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7 create mode 100644 external/boringssl/fuzz/server_corpus/65ee094875fb0e661e0a83872c5ef2a2b96456d3 create mode 100644 external/boringssl/fuzz/server_corpus/663aac853a26b5b7d366b1084fa0b89e8c1042c7 create mode 100644 external/boringssl/fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10 create mode 100644 external/boringssl/fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739f create mode 100644 external/boringssl/fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78 create mode 100644 external/boringssl/fuzz/server_corpus/6ad9e29108e9b826b4ae5ef1b6748dcaee3647bb create mode 100644 external/boringssl/fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02ce create mode 100644 external/boringssl/fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7 create mode 100644 external/boringssl/fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753 create mode 100644 external/boringssl/fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5c create mode 100644 external/boringssl/fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06 create mode 100644 external/boringssl/fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532c create mode 100644 external/boringssl/fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0 create mode 100644 external/boringssl/fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359 create mode 100644 external/boringssl/fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890 create mode 100644 external/boringssl/fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a create mode 100644 external/boringssl/fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83be create mode 100644 external/boringssl/fuzz/server_corpus/703da7bc1a86d25c4a719ffd8dd758eb593d151c create mode 100644 external/boringssl/fuzz/server_corpus/706f54bf24538976566b61e852b1c4d9ae1119f4 create mode 100644 external/boringssl/fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634 create mode 100644 external/boringssl/fuzz/server_corpus/70c37f8fac66c1b1246354d4c7236ee2dc283e5c create mode 100644 external/boringssl/fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aad create mode 100644 external/boringssl/fuzz/server_corpus/75cc89a6fd3156770999a138f3d2a050344364ad create mode 100644 external/boringssl/fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af create mode 100644 external/boringssl/fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232 create mode 100644 external/boringssl/fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58 create mode 100644 external/boringssl/fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93e create mode 100644 external/boringssl/fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762d create mode 100644 external/boringssl/fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2 create mode 100644 external/boringssl/fuzz/server_corpus/7c7edef35a80358b098ede960f7a254c2920b945 create mode 100644 external/boringssl/fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457f create mode 100644 external/boringssl/fuzz/server_corpus/7cd231570a9a7ba088cc00447c836839564bdc71 create mode 100644 external/boringssl/fuzz/server_corpus/7d70d47487b1c99d7a154307e976905551bff147 create mode 100644 external/boringssl/fuzz/server_corpus/7d7bf92eb0b77728910683eb97d356df3bcafd01 create mode 100644 external/boringssl/fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10 create mode 100644 external/boringssl/fuzz/server_corpus/7eb254ed656a33e05bdc3def3565b7ef45d30cee create mode 100644 external/boringssl/fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35 create mode 100644 external/boringssl/fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02 create mode 100644 external/boringssl/fuzz/server_corpus/7f762ef581bf5b21dc2b9e5d0a6f01556d02827d create mode 100644 external/boringssl/fuzz/server_corpus/7fd784bcc4b1e7cca034bd5e90d013cdd5ed37fc create mode 100644 external/boringssl/fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943a create mode 100644 external/boringssl/fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2 create mode 100644 external/boringssl/fuzz/server_corpus/805673ac41123503f5ec4d5a5b26d0c49751d219 create mode 100644 external/boringssl/fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079 create mode 100644 external/boringssl/fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538e create mode 100644 external/boringssl/fuzz/server_corpus/8130aa1cfff870363a58b1aed00aeddbd08e3439 create mode 100644 external/boringssl/fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1a create mode 100644 external/boringssl/fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629 create mode 100644 external/boringssl/fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9 create mode 100644 external/boringssl/fuzz/server_corpus/81aed319be7488358f8fbf252561c12c68f88a96 create mode 100644 external/boringssl/fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27 create mode 100644 external/boringssl/fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4 create mode 100644 external/boringssl/fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095 create mode 100644 external/boringssl/fuzz/server_corpus/84128b248dde02f39d9038b0d9a92be858064b93 create mode 100644 external/boringssl/fuzz/server_corpus/846f489beaa418c54a7558e3dda22fa18a613344 create mode 100644 external/boringssl/fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1 create mode 100644 external/boringssl/fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097 create mode 100644 external/boringssl/fuzz/server_corpus/8550e0986e06c2c732bf5707cf1679d18d4018a7 create mode 100644 external/boringssl/fuzz/server_corpus/865424250f3372fd80022ecbd3030371eb7484bb create mode 100644 external/boringssl/fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77 create mode 100644 external/boringssl/fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01 create mode 100644 external/boringssl/fuzz/server_corpus/87d63b2cf65c4a56d5c6c7354e122472c1c86985 create mode 100644 external/boringssl/fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9 create mode 100644 external/boringssl/fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6 create mode 100644 external/boringssl/fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c create mode 100644 external/boringssl/fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338 create mode 100644 external/boringssl/fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4 create mode 100644 external/boringssl/fuzz/server_corpus/8dc9927297dc363f7858864279aba3d2e7f1abea create mode 100644 external/boringssl/fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779 create mode 100644 external/boringssl/fuzz/server_corpus/90d7f98a4df715ea087a5ac5f96c20d968cdfa11 create mode 100644 external/boringssl/fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006 create mode 100644 external/boringssl/fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86 create mode 100644 external/boringssl/fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41d create mode 100644 external/boringssl/fuzz/server_corpus/968d9f7d5bf7e11e205dedf844a771f185c777a0 create mode 100644 external/boringssl/fuzz/server_corpus/96e88c6539e937f868152998ba46a8decab25bf6 create mode 100644 external/boringssl/fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726 create mode 100644 external/boringssl/fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358 create mode 100644 external/boringssl/fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13ca create mode 100644 external/boringssl/fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335 create mode 100644 external/boringssl/fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcb create mode 100644 external/boringssl/fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0 create mode 100644 external/boringssl/fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74 create mode 100644 external/boringssl/fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3ad create mode 100644 external/boringssl/fuzz/server_corpus/9d6670b22713ef933f7023a1de30f1bf0f153b7c create mode 100644 external/boringssl/fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4c create mode 100644 external/boringssl/fuzz/server_corpus/a17c22b54007188166fa0ddc4afc05dce426bd06 create mode 100644 external/boringssl/fuzz/server_corpus/a2119075a436f488b9caddcd0d2e78f08eb9a5ff create mode 100644 external/boringssl/fuzz/server_corpus/a38a19f50fd1cda8c1fecbe27ac83324ca211b84 create mode 100644 external/boringssl/fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b create mode 100644 external/boringssl/fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3ac create mode 100644 external/boringssl/fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5 create mode 100644 external/boringssl/fuzz/server_corpus/a522a19032823024bb19fd0df2d4f26ea54a896d create mode 100644 external/boringssl/fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39ac create mode 100644 external/boringssl/fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9 create mode 100644 external/boringssl/fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1a create mode 100644 external/boringssl/fuzz/server_corpus/a8461484408a8b22ac775b72a0fae9362e1bbf46 create mode 100644 external/boringssl/fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786b create mode 100644 external/boringssl/fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085f create mode 100644 external/boringssl/fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715 create mode 100644 external/boringssl/fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cb create mode 100644 external/boringssl/fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75 create mode 100644 external/boringssl/fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498 create mode 100644 external/boringssl/fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79 create mode 100644 external/boringssl/fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221b create mode 100644 external/boringssl/fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27 create mode 100644 external/boringssl/fuzz/server_corpus/b110009f633e2daf74b775a2f29521e49cb50021 create mode 100644 external/boringssl/fuzz/server_corpus/b161a1165fdcc35082d791714fa697f88f673f32 create mode 100644 external/boringssl/fuzz/server_corpus/b19d4db2ac81eca8ec7270e840ade3c0d0f9c961 create mode 100644 external/boringssl/fuzz/server_corpus/b34fe229d5704686c2f583c49081e780f9eee0f0 create mode 100644 external/boringssl/fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74 create mode 100644 external/boringssl/fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518c create mode 100644 external/boringssl/fuzz/server_corpus/b5e350594b8a451635004e4adbac220855746f95 create mode 100644 external/boringssl/fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938 create mode 100644 external/boringssl/fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571 create mode 100644 external/boringssl/fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9b create mode 100644 external/boringssl/fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902f create mode 100644 external/boringssl/fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368 create mode 100644 external/boringssl/fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32 create mode 100644 external/boringssl/fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257 create mode 100644 external/boringssl/fuzz/server_corpus/b7dcbba77174c4a08c659a593ec3f5ebe5094343 create mode 100644 external/boringssl/fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5e create mode 100644 external/boringssl/fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7e create mode 100644 external/boringssl/fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bf create mode 100644 external/boringssl/fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9c create mode 100644 external/boringssl/fuzz/server_corpus/bb589d0621e5472f470fa3425a234c74b1e202e8 create mode 100644 external/boringssl/fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8 create mode 100644 external/boringssl/fuzz/server_corpus/bd2f13c2ea9251c8f5984e4801964d2c535e979a create mode 100644 external/boringssl/fuzz/server_corpus/bd6b8551ceeb4f504ef7428a1fe188ad343c9e70 create mode 100644 external/boringssl/fuzz/server_corpus/be6b4b2ec34f17afc2630bd13ceda59817a86bf0 create mode 100644 external/boringssl/fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7f create mode 100644 external/boringssl/fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72 create mode 100644 external/boringssl/fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246 create mode 100644 external/boringssl/fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0 create mode 100644 external/boringssl/fuzz/server_corpus/c1774d0621d44733a05eb58edf38f7f994ada191 create mode 100644 external/boringssl/fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abb create mode 100644 external/boringssl/fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8d create mode 100644 external/boringssl/fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8 create mode 100644 external/boringssl/fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84 create mode 100644 external/boringssl/fuzz/server_corpus/c3b18d830d2afda016d1c6d2cf8656707936d9aa create mode 100644 external/boringssl/fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25 create mode 100644 external/boringssl/fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40ee create mode 100644 external/boringssl/fuzz/server_corpus/c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 create mode 100644 external/boringssl/fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671 create mode 100644 external/boringssl/fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122 create mode 100644 external/boringssl/fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910 create mode 100644 external/boringssl/fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3ac create mode 100644 external/boringssl/fuzz/server_corpus/c7ca9b384fb874d12f54ba800b7db3fc35d47d1a create mode 100644 external/boringssl/fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7 create mode 100644 external/boringssl/fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970 create mode 100644 external/boringssl/fuzz/server_corpus/c92efc4a4757c37f8373d5da954b114eb780dc52 create mode 100644 external/boringssl/fuzz/server_corpus/cab79dd0612ba0a5213ad42c88619860f9e9485b create mode 100644 external/boringssl/fuzz/server_corpus/cb0bbbd9c59f0dc9dd030885b65afb8524a4fd45 create mode 100644 external/boringssl/fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590d create mode 100644 external/boringssl/fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2 create mode 100644 external/boringssl/fuzz/server_corpus/cc646165768ece9d7b3a53295139c652758719eb create mode 100644 external/boringssl/fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800 create mode 100644 external/boringssl/fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc create mode 100644 external/boringssl/fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743 create mode 100644 external/boringssl/fuzz/server_corpus/cef9da3480218f4a353a1d4b10d5095b2273be49 create mode 100644 external/boringssl/fuzz/server_corpus/cf4553b998285a8ef7bcfbb845288955302344b0 create mode 100644 external/boringssl/fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75 create mode 100644 external/boringssl/fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912 create mode 100644 external/boringssl/fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9 create mode 100644 external/boringssl/fuzz/server_corpus/d0846c7f54810ba3483ecaaa84e73b5c87fb72fb create mode 100644 external/boringssl/fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488ce create mode 100644 external/boringssl/fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6 create mode 100644 external/boringssl/fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9 create mode 100644 external/boringssl/fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079 create mode 100644 external/boringssl/fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799 create mode 100644 external/boringssl/fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767e create mode 100644 external/boringssl/fuzz/server_corpus/d34d64db9a73ba104b383f991f4ed92a60987cf5 create mode 100644 external/boringssl/fuzz/server_corpus/d374b7d09d4196c596a2586a88256fcb1e9fcb2e create mode 100644 external/boringssl/fuzz/server_corpus/d37f0db1910aa2e906b546fc035f2831addcde43 create mode 100644 external/boringssl/fuzz/server_corpus/d3a86e7b61070b78611766d587f5c1bae1786b32 create mode 100644 external/boringssl/fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773 create mode 100644 external/boringssl/fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72 create mode 100644 external/boringssl/fuzz/server_corpus/d4f46b0706389e9680ae047f98bdf38bc31eabd2 create mode 100644 external/boringssl/fuzz/server_corpus/d503f0f105b563087338bf3517a269ba8b130f1c create mode 100644 external/boringssl/fuzz/server_corpus/d6a617adce65f5e26d0b216b04cf5faf774ae5df create mode 100644 external/boringssl/fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60 create mode 100644 external/boringssl/fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447 create mode 100644 external/boringssl/fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27 create mode 100644 external/boringssl/fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8 create mode 100644 external/boringssl/fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1 create mode 100644 external/boringssl/fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0 create mode 100644 external/boringssl/fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677 create mode 100644 external/boringssl/fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434 create mode 100644 external/boringssl/fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9a create mode 100644 external/boringssl/fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e create mode 100644 external/boringssl/fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5 create mode 100644 external/boringssl/fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5f create mode 100644 external/boringssl/fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155 create mode 100644 external/boringssl/fuzz/server_corpus/df0c69339b2d0625f2114cc0665bf85726fd7737 create mode 100644 external/boringssl/fuzz/server_corpus/df38c584e0a47097ffb84eeeb233378bbe4adb27 create mode 100644 external/boringssl/fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0e create mode 100644 external/boringssl/fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1 create mode 100644 external/boringssl/fuzz/server_corpus/e2c8667b857090a2a76111235b1dda0410d0531b create mode 100644 external/boringssl/fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11 create mode 100644 external/boringssl/fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846e create mode 100644 external/boringssl/fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60 create mode 100644 external/boringssl/fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf create mode 100644 external/boringssl/fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3c create mode 100644 external/boringssl/fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2b create mode 100644 external/boringssl/fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557 create mode 100644 external/boringssl/fuzz/server_corpus/e82e55fa1dc031602bd9db99ef3bfba52828a7e7 create mode 100644 external/boringssl/fuzz/server_corpus/e94b2714af564e9e3ee8b464514a55c2ed46d8ba create mode 100644 external/boringssl/fuzz/server_corpus/ebe605930e73da69d25b156cff9dbd13f0861484 create mode 100644 external/boringssl/fuzz/server_corpus/ebe60c3b30c6c5bd1ce23e3a033ddfeb4515b303 create mode 100644 external/boringssl/fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874 create mode 100644 external/boringssl/fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976 create mode 100644 external/boringssl/fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41dec create mode 100644 external/boringssl/fuzz/server_corpus/eeb0f79e9507ef27c237ddaac2fc859a1fee8bc9 create mode 100644 external/boringssl/fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4 create mode 100644 external/boringssl/fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679d create mode 100644 external/boringssl/fuzz/server_corpus/f00bdfcb2a5a22ef03bbdcc3e661335eb4d11c84 create mode 100644 external/boringssl/fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18 create mode 100644 external/boringssl/fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30 create mode 100644 external/boringssl/fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86 create mode 100644 external/boringssl/fuzz/server_corpus/f1ee7dd7ebf5b68a385e5dc1f289116c67aa5fd5 create mode 100644 external/boringssl/fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691b create mode 100644 external/boringssl/fuzz/server_corpus/f34cbb130fef3f89599402ea6d721b7eb3e5615d create mode 100644 external/boringssl/fuzz/server_corpus/f38adbdf7df8def4641eeb1a28ce0ecf8d9b2fe1 create mode 100644 external/boringssl/fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134a create mode 100644 external/boringssl/fuzz/server_corpus/f4425d6adf697df0f85be8758c0cd21d6a5df57a create mode 100644 external/boringssl/fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322 create mode 100644 external/boringssl/fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9 create mode 100644 external/boringssl/fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6 create mode 100644 external/boringssl/fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0b create mode 100644 external/boringssl/fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149e create mode 100644 external/boringssl/fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82 create mode 100644 external/boringssl/fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1 create mode 100644 external/boringssl/fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685 create mode 100644 external/boringssl/fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99 create mode 100644 external/boringssl/fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38 create mode 100644 external/boringssl/fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61 create mode 100644 external/boringssl/fuzz/server_corpus/fe9517d5de1d6e4b9d9fa9cc67e809b697e61886 create mode 100644 external/boringssl/fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07db create mode 100644 external/boringssl/fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602 create mode 100644 external/boringssl/fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0f create mode 100644 external/boringssl/fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439 create mode 100644 external/boringssl/fuzz/spki.cc create mode 100644 external/boringssl/fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263ee create mode 100644 external/boringssl/fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3a create mode 100644 external/boringssl/fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548f create mode 100644 external/boringssl/fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587 create mode 100644 external/boringssl/fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0c create mode 100644 external/boringssl/fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915 create mode 100644 external/boringssl/fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00 create mode 100644 external/boringssl/fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6 create mode 100644 external/boringssl/include/openssl/aead.h create mode 100644 external/boringssl/include/openssl/aes.h create mode 100644 external/boringssl/include/openssl/arm_arch.h create mode 100644 external/boringssl/include/openssl/asn1.h create mode 100644 external/boringssl/include/openssl/asn1_mac.h create mode 100644 external/boringssl/include/openssl/asn1t.h create mode 100644 external/boringssl/include/openssl/base.h create mode 100644 external/boringssl/include/openssl/base64.h create mode 100644 external/boringssl/include/openssl/bio.h create mode 100644 external/boringssl/include/openssl/blowfish.h create mode 100644 external/boringssl/include/openssl/bn.h create mode 100644 external/boringssl/include/openssl/buf.h create mode 100644 external/boringssl/include/openssl/buffer.h create mode 100644 external/boringssl/include/openssl/bytestring.h create mode 100644 external/boringssl/include/openssl/cast.h create mode 100644 external/boringssl/include/openssl/chacha.h create mode 100644 external/boringssl/include/openssl/cipher.h create mode 100644 external/boringssl/include/openssl/cmac.h create mode 100644 external/boringssl/include/openssl/conf.h create mode 100644 external/boringssl/include/openssl/cpu.h create mode 100644 external/boringssl/include/openssl/crypto.h create mode 100644 external/boringssl/include/openssl/curve25519.h create mode 100644 external/boringssl/include/openssl/des.h create mode 100644 external/boringssl/include/openssl/dh.h create mode 100644 external/boringssl/include/openssl/digest.h create mode 100644 external/boringssl/include/openssl/dsa.h create mode 100644 external/boringssl/include/openssl/dtls1.h create mode 100644 external/boringssl/include/openssl/ec.h create mode 100644 external/boringssl/include/openssl/ec_key.h create mode 100644 external/boringssl/include/openssl/ecdh.h create mode 100644 external/boringssl/include/openssl/ecdsa.h create mode 100644 external/boringssl/include/openssl/engine.h create mode 100644 external/boringssl/include/openssl/err.h create mode 100644 external/boringssl/include/openssl/evp.h create mode 100644 external/boringssl/include/openssl/ex_data.h create mode 100644 external/boringssl/include/openssl/hkdf.h create mode 100644 external/boringssl/include/openssl/hmac.h create mode 100644 external/boringssl/include/openssl/lhash.h create mode 100644 external/boringssl/include/openssl/lhash_macros.h create mode 100644 external/boringssl/include/openssl/md4.h create mode 100644 external/boringssl/include/openssl/md5.h create mode 100644 external/boringssl/include/openssl/mem.h create mode 100644 external/boringssl/include/openssl/newhope.h create mode 100644 external/boringssl/include/openssl/nid.h.REMOVED.git-id create mode 100644 external/boringssl/include/openssl/obj.h create mode 100644 external/boringssl/include/openssl/obj_mac.h create mode 100644 external/boringssl/include/openssl/objects.h create mode 100644 external/boringssl/include/openssl/opensslconf.h create mode 100644 external/boringssl/include/openssl/opensslv.h create mode 100644 external/boringssl/include/openssl/ossl_typ.h create mode 100644 external/boringssl/include/openssl/pem.h create mode 100644 external/boringssl/include/openssl/pkcs12.h create mode 100644 external/boringssl/include/openssl/pkcs7.h create mode 100644 external/boringssl/include/openssl/pkcs8.h create mode 100644 external/boringssl/include/openssl/poly1305.h create mode 100644 external/boringssl/include/openssl/pqueue.h create mode 100644 external/boringssl/include/openssl/rand.h create mode 100644 external/boringssl/include/openssl/rc4.h create mode 100644 external/boringssl/include/openssl/ripemd.h create mode 100644 external/boringssl/include/openssl/rsa.h create mode 100644 external/boringssl/include/openssl/safestack.h create mode 100644 external/boringssl/include/openssl/sha.h create mode 100644 external/boringssl/include/openssl/srtp.h create mode 100644 external/boringssl/include/openssl/ssl.h.REMOVED.git-id create mode 100644 external/boringssl/include/openssl/ssl3.h create mode 100644 external/boringssl/include/openssl/stack.h create mode 100644 external/boringssl/include/openssl/stack_macros.h.REMOVED.git-id create mode 100644 external/boringssl/include/openssl/thread.h create mode 100644 external/boringssl/include/openssl/time_support.h create mode 100644 external/boringssl/include/openssl/tls1.h create mode 100644 external/boringssl/include/openssl/type_check.h create mode 100644 external/boringssl/include/openssl/x509.h create mode 100644 external/boringssl/include/openssl/x509_vfy.h create mode 100644 external/boringssl/include/openssl/x509v3.h create mode 100644 external/boringssl/ssl/CMakeLists.txt create mode 100644 external/boringssl/ssl/custom_extensions.c create mode 100644 external/boringssl/ssl/d1_both.c create mode 100644 external/boringssl/ssl/d1_lib.c create mode 100644 external/boringssl/ssl/d1_meth.c create mode 100644 external/boringssl/ssl/d1_pkt.c create mode 100644 external/boringssl/ssl/d1_srtp.c create mode 100644 external/boringssl/ssl/dtls_record.c create mode 100644 external/boringssl/ssl/handshake_client.c create mode 100644 external/boringssl/ssl/handshake_server.c create mode 100644 external/boringssl/ssl/internal.h create mode 100644 external/boringssl/ssl/pqueue/CMakeLists.txt create mode 100644 external/boringssl/ssl/pqueue/pqueue.c create mode 100644 external/boringssl/ssl/pqueue/pqueue_test.c create mode 100644 external/boringssl/ssl/s3_both.c create mode 100644 external/boringssl/ssl/s3_enc.c create mode 100644 external/boringssl/ssl/s3_lib.c create mode 100644 external/boringssl/ssl/s3_meth.c create mode 100644 external/boringssl/ssl/s3_pkt.c create mode 100644 external/boringssl/ssl/ssl_aead_ctx.c create mode 100644 external/boringssl/ssl/ssl_asn1.c create mode 100644 external/boringssl/ssl/ssl_buffer.c create mode 100644 external/boringssl/ssl/ssl_cert.c create mode 100644 external/boringssl/ssl/ssl_cipher.c create mode 100644 external/boringssl/ssl/ssl_ecdh.c create mode 100644 external/boringssl/ssl/ssl_file.c create mode 100644 external/boringssl/ssl/ssl_lib.c create mode 100644 external/boringssl/ssl/ssl_rsa.c create mode 100644 external/boringssl/ssl/ssl_session.c create mode 100644 external/boringssl/ssl/ssl_stat.c create mode 100644 external/boringssl/ssl/ssl_test.cc create mode 100644 external/boringssl/ssl/t1_enc.c create mode 100644 external/boringssl/ssl/t1_lib.c create mode 100644 external/boringssl/ssl/test/CMakeLists.txt create mode 100644 external/boringssl/ssl/test/README.md create mode 100644 external/boringssl/ssl/test/async_bio.cc create mode 100644 external/boringssl/ssl/test/async_bio.h create mode 100644 external/boringssl/ssl/test/bssl_shim.cc create mode 100644 external/boringssl/ssl/test/packeted_bio.cc create mode 100644 external/boringssl/ssl/test/packeted_bio.h create mode 100644 external/boringssl/ssl/test/runner/alert.go create mode 100644 external/boringssl/ssl/test/runner/cert.pem create mode 100644 external/boringssl/ssl/test/runner/chacha20_poly1305.go create mode 100644 external/boringssl/ssl/test/runner/chacha20_poly1305_test.go create mode 100644 external/boringssl/ssl/test/runner/channel_id_key.pem create mode 100644 external/boringssl/ssl/test/runner/cipher_suites.go create mode 100644 external/boringssl/ssl/test/runner/common.go create mode 100644 external/boringssl/ssl/test/runner/conn.go create mode 100644 external/boringssl/ssl/test/runner/curve25519/const_amd64.s create mode 100644 external/boringssl/ssl/test/runner/curve25519/cswap_amd64.s create mode 100644 external/boringssl/ssl/test/runner/curve25519/curve25519.go create mode 100644 external/boringssl/ssl/test/runner/curve25519/curve25519_test.go create mode 100644 external/boringssl/ssl/test/runner/curve25519/doc.go create mode 100644 external/boringssl/ssl/test/runner/curve25519/freeze_amd64.s create mode 100644 external/boringssl/ssl/test/runner/curve25519/ladderstep_amd64.s create mode 100644 external/boringssl/ssl/test/runner/curve25519/mont25519_amd64.go create mode 100644 external/boringssl/ssl/test/runner/curve25519/mul_amd64.s create mode 100644 external/boringssl/ssl/test/runner/curve25519/square_amd64.s create mode 100644 external/boringssl/ssl/test/runner/deterministic.go create mode 100644 external/boringssl/ssl/test/runner/dtls.go create mode 100644 external/boringssl/ssl/test/runner/ecdsa_cert.pem create mode 100644 external/boringssl/ssl/test/runner/ecdsa_key.pem create mode 100644 external/boringssl/ssl/test/runner/handshake_client.go create mode 100644 external/boringssl/ssl/test/runner/handshake_messages.go create mode 100644 external/boringssl/ssl/test/runner/handshake_server.go create mode 100644 external/boringssl/ssl/test/runner/key.pem create mode 100644 external/boringssl/ssl/test/runner/key_agreement.go create mode 100644 external/boringssl/ssl/test/runner/newhope/newhope.go create mode 100644 external/boringssl/ssl/test/runner/newhope/newhope_test.go create mode 100644 external/boringssl/ssl/test/runner/newhope/reconciliation.go create mode 100644 external/boringssl/ssl/test/runner/packet_adapter.go create mode 100644 external/boringssl/ssl/test/runner/poly1305/const_amd64.s create mode 100644 external/boringssl/ssl/test/runner/poly1305/poly1305.go create mode 100644 external/boringssl/ssl/test/runner/poly1305/poly1305_amd64.s create mode 100644 external/boringssl/ssl/test/runner/poly1305/poly1305_arm.s create mode 100644 external/boringssl/ssl/test/runner/poly1305/poly1305_test.go create mode 100644 external/boringssl/ssl/test/runner/poly1305/sum_amd64.go create mode 100644 external/boringssl/ssl/test/runner/poly1305/sum_arm.go create mode 100644 external/boringssl/ssl/test/runner/poly1305/sum_ref.go create mode 100644 external/boringssl/ssl/test/runner/prf.go create mode 100644 external/boringssl/ssl/test/runner/recordingconn.go create mode 100644 external/boringssl/ssl/test/runner/runner.go.REMOVED.git-id create mode 100644 external/boringssl/ssl/test/runner/runner_test.go create mode 100644 external/boringssl/ssl/test/runner/test_output.go create mode 100644 external/boringssl/ssl/test/runner/ticket.go create mode 100644 external/boringssl/ssl/test/runner/tls.go create mode 100644 external/boringssl/ssl/test/scoped_types.h create mode 100644 external/boringssl/ssl/test/test_config.cc create mode 100644 external/boringssl/ssl/test/test_config.h create mode 100644 external/boringssl/ssl/tls_record.c create mode 100644 external/boringssl/third_party/android-cmake/AndroidNdkGdb.cmake create mode 100644 external/boringssl/third_party/android-cmake/AndroidNdkModules.cmake create mode 100644 external/boringssl/third_party/android-cmake/LICENSE create mode 100644 external/boringssl/third_party/android-cmake/README.google create mode 100644 external/boringssl/third_party/android-cmake/README.md create mode 100644 external/boringssl/third_party/android-cmake/android.toolchain.cmake create mode 100644 external/boringssl/third_party/android-cmake/ndk_links.md create mode 100644 external/boringssl/tool/CMakeLists.txt create mode 100644 external/boringssl/tool/args.cc create mode 100644 external/boringssl/tool/ciphers.cc create mode 100644 external/boringssl/tool/client.cc create mode 100644 external/boringssl/tool/const.cc create mode 100644 external/boringssl/tool/digest.cc create mode 100644 external/boringssl/tool/generate_ed25519.cc create mode 100644 external/boringssl/tool/genrsa.cc create mode 100644 external/boringssl/tool/internal.h create mode 100644 external/boringssl/tool/pkcs12.cc create mode 100644 external/boringssl/tool/rand.cc create mode 100644 external/boringssl/tool/server.cc create mode 100644 external/boringssl/tool/speed.cc create mode 100644 external/boringssl/tool/tool.cc create mode 100644 external/boringssl/tool/transport_common.cc create mode 100644 external/boringssl/tool/transport_common.h create mode 100644 external/boringssl/util/32-bit-toolchain.cmake create mode 100644 external/boringssl/util/all_tests.go create mode 100644 external/boringssl/util/all_tests.json create mode 100644 external/boringssl/util/android-cmake/.gitattributes create mode 100644 external/boringssl/util/android-cmake/.gitignore create mode 100644 external/boringssl/util/android-cmake/AndroidNdkGdb.cmake create mode 100644 external/boringssl/util/android-cmake/AndroidNdkModules.cmake create mode 100644 external/boringssl/util/android-cmake/README.md create mode 100644 external/boringssl/util/android-cmake/android.toolchain.cmake create mode 100644 external/boringssl/util/android-cmake/ndk_links.md create mode 100644 external/boringssl/util/bot/DEPS create mode 100644 external/boringssl/util/bot/README create mode 100644 external/boringssl/util/bot/UPDATING create mode 100644 external/boringssl/util/bot/cmake-linux64.tar.gz.sha1 create mode 100644 external/boringssl/util/bot/cmake-mac.tar.gz.sha1 create mode 100644 external/boringssl/util/bot/cmake-win32.zip.sha1 create mode 100644 external/boringssl/util/bot/extract.py create mode 100755 external/boringssl/util/bot/go/bootstrap.py create mode 100755 external/boringssl/util/bot/go/env.py create mode 100644 external/boringssl/util/bot/perl-win32.zip.sha1 create mode 100644 external/boringssl/util/bot/update_clang.py create mode 100644 external/boringssl/util/bot/vs_env.py create mode 100644 external/boringssl/util/bot/vs_toolchain.py create mode 100644 external/boringssl/util/bot/yasm-win32.exe.sha1 create mode 100644 external/boringssl/util/doc.config create mode 100644 external/boringssl/util/doc.css create mode 100644 external/boringssl/util/doc.go create mode 100755 external/boringssl/util/generate-asm-lcov.py create mode 100755 external/boringssl/util/generate-coverage.sh create mode 100644 external/boringssl/util/generate_build_files.py create mode 100644 external/boringssl/util/make_errors.go create mode 100644 external/boringssl/util/run_android_tests.go create mode 100644 external/cecil-legacy/.gitattributes create mode 100644 external/cecil-legacy/.gitignore create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/Code.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/CodeReader.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/CodeWriter.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/Document.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/ExceptionHandler.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/ILProcessor.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/Instruction.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/MethodBody.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/OpCode.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/OpCodes.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/SequencePoint.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/Symbols.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/VariableDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Cil/VariableReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/BlobHeap.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/Buffers.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/CodedIndex.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/ElementType.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/GuidHeap.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/Heap.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/MetadataToken.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/Row.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/StringHeap.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/TableHeap.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/TokenType.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/UserStringHeap.cs create mode 100644 external/cecil-legacy/Mono.Cecil.Metadata/Utilities.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/BinaryStreamReader.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/BinaryStreamWriter.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/ByteBuffer.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/ByteBufferEqualityComparer.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/DataDirectory.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/Image.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/ImageReader.cs create mode 100644 external/cecil-legacy/Mono.Cecil.PE/ImageWriter.cs rename mcs/tools/mconfig/Mono.MonoConfig/consts.cs.in => external/cecil-legacy/Mono.Cecil.PE/Section.cs (75%) create mode 100644 external/cecil-legacy/Mono.Cecil.PE/TextMap.cs create mode 100644 external/cecil-legacy/Mono.Cecil.csproj create mode 100755 external/cecil-legacy/Mono.Cecil.nunit create mode 100644 external/cecil-legacy/Mono.Cecil.nuspec create mode 100644 external/cecil-legacy/Mono.Cecil.sln create mode 100755 external/cecil-legacy/Mono.Cecil.sln.DotSettings create mode 100644 external/cecil-legacy/Mono.Cecil/ArrayType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/AssemblyDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/AssemblyFlags.cs rename mcs/class/corlib/System/GCNotificationStatus.cs => external/cecil-legacy/Mono.Cecil/AssemblyHashAlgorithm.cs (75%) create mode 100644 external/cecil-legacy/Mono.Cecil/AssemblyInfo.cs rename mcs/class/System/System.Security.Authentication.ExtendedProtection/ServiceNameCollection.cs => external/cecil-legacy/Mono.Cecil/AssemblyLinkedResource.cs (60%) rename mcs/class/System/System.Diagnostics.CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs => external/cecil-legacy/Mono.Cecil/AssemblyNameDefinition.cs (67%) create mode 100644 external/cecil-legacy/Mono.Cecil/AssemblyNameReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/AssemblyReader.cs create mode 100644 external/cecil-legacy/Mono.Cecil/AssemblyWriter.cs create mode 100644 external/cecil-legacy/Mono.Cecil/BaseAssemblyResolver.cs create mode 100644 external/cecil-legacy/Mono.Cecil/CallSite.cs create mode 100644 external/cecil-legacy/Mono.Cecil/CustomAttribute.cs create mode 100644 external/cecil-legacy/Mono.Cecil/DefaultAssemblyResolver.cs create mode 100644 external/cecil-legacy/Mono.Cecil/EmbeddedResource.cs create mode 100644 external/cecil-legacy/Mono.Cecil/EventAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/EventDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/EventReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ExportedType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/FieldAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/FieldDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/FieldReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/FileAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/FunctionPointerType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/GenericInstanceMethod.cs create mode 100644 external/cecil-legacy/Mono.Cecil/GenericInstanceType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/GenericParameter.cs create mode 100644 external/cecil-legacy/Mono.Cecil/GenericParameterAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/IConstantProvider.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ICustomAttributeProvider.cs rename mcs/class/corlib/System.Reflection/TargetInvocationException.cs => external/cecil-legacy/Mono.Cecil/IGenericInstance.cs (53%) create mode 100644 external/cecil-legacy/Mono.Cecil/IGenericParameterProvider.cs create mode 100644 external/cecil-legacy/Mono.Cecil/IMarshalInfoProvider.cs create mode 100644 external/cecil-legacy/Mono.Cecil/IMemberDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/IMetadataScope.cs create mode 100644 external/cecil-legacy/Mono.Cecil/IMetadataTokenProvider.cs create mode 100644 external/cecil-legacy/Mono.Cecil/IMethodSignature.cs create mode 100644 external/cecil-legacy/Mono.Cecil/Import.cs create mode 100644 external/cecil-legacy/Mono.Cecil/LinkedResource.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ManifestResourceAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MarshalInfo.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MemberDefinitionCollection.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MemberReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MetadataResolver.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MetadataSystem.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodCallingConvention.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodImplAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodReturnType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodSemanticsAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/MethodSpecification.cs create mode 100644 external/cecil-legacy/Mono.Cecil/Modifiers.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ModuleDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ModuleKind.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ModuleReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/NativeType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/PInvokeAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/PInvokeInfo.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ParameterAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ParameterDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ParameterDefinitionCollection.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ParameterReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/PinnedType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/PointerType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/PropertyAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/PropertyDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/PropertyReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/ReferenceType.cs create mode 100644 external/cecil-legacy/Mono.Cecil/Resource.cs create mode 100644 external/cecil-legacy/Mono.Cecil/SecurityDeclaration.cs create mode 100644 external/cecil-legacy/Mono.Cecil/SentinelType.cs rename mcs/class/corlib/System/GCCollectionMode.cs => external/cecil-legacy/Mono.Cecil/TargetRuntime.cs (82%) create mode 100644 external/cecil-legacy/Mono.Cecil/TypeAttributes.cs create mode 100644 external/cecil-legacy/Mono.Cecil/TypeDefinition.cs create mode 100644 external/cecil-legacy/Mono.Cecil/TypeDefinitionCollection.cs create mode 100644 external/cecil-legacy/Mono.Cecil/TypeParser.cs create mode 100644 external/cecil-legacy/Mono.Cecil/TypeReference.cs create mode 100644 external/cecil-legacy/Mono.Cecil/TypeSpecification.cs create mode 100644 external/cecil-legacy/Mono.Cecil/TypeSystem.cs create mode 100644 external/cecil-legacy/Mono.Cecil/VariantType.cs create mode 100644 external/cecil-legacy/Mono.Collections.Generic/Collection.cs create mode 100644 external/cecil-legacy/Mono.Collections.Generic/ReadOnlyCollection.cs create mode 100644 external/cecil-legacy/Mono.Security.Cryptography/CryptoConvert.cs create mode 100644 external/cecil-legacy/Mono.Security.Cryptography/CryptoService.cs rename external/{cecil => cecil-legacy}/Mono/Actions.cs (100%) create mode 100644 external/cecil-legacy/Mono/Empty.cs rename external/{cecil => cecil-legacy}/Mono/Funcs.cs (100%) rename external/{cecil => cecil-legacy}/NOTES.txt (100%) rename external/{cecil => cecil-legacy}/System.Runtime.CompilerServices/ExtensionAttribute.cs (100%) rename external/{cecil => cecil-legacy}/Test/.gitignore (100%) create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests.csproj rename external/{cecil => cecil-legacy}/Test/Mono.Cecil.Tests/Addin.cs (100%) create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyInfo.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/BaseTestFixture.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/CompilationService.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/CustomAttributesTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/EventTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/Extensions.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/FieldTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/Formatter.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/ILProcessorTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/ImageReadTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/ImportCecilTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/ImportReflectionTests.cs rename external/{cecil => cecil-legacy}/Test/Mono.Cecil.Tests/Linq.cs (100%) create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/MethodBodyTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/MethodTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/ModuleTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/NestedTypesTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/ParameterTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/PropertyTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/ResolveTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/TypeParserTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/TypeTests.cs create mode 100644 external/cecil-legacy/Test/Mono.Cecil.Tests/VariableTests.cs create mode 100644 external/cecil-legacy/Test/Resources/assemblies/moda.netmodule create mode 100644 external/cecil-legacy/Test/Resources/assemblies/modb.netmodule create mode 100644 external/cecil-legacy/Test/Resources/assemblies/text_file.txt create mode 100644 external/cecil-legacy/Test/Resources/cs/CustomAttributes.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/Events.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/Fields.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/Generics.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/Interfaces.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/Layouts.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/Methods.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/NestedTypes.cs create mode 100644 external/cecil-legacy/Test/Resources/cs/Properties.cs create mode 100644 external/cecil-legacy/Test/Resources/il/explicitthis.il create mode 100644 external/cecil-legacy/Test/Resources/il/hello.il create mode 100644 external/cecil-legacy/Test/Resources/il/methodspecs.il create mode 100644 external/cecil-legacy/Test/Resources/il/others.il create mode 100644 external/cecil-legacy/Test/Resources/il/types.il create mode 100755 external/cecil-legacy/Test/libs/nunit-2.6.2/license.txt rename external/{cecil => cecil-legacy}/dbg/Program.cs (100%) rename external/{cecil => cecil-legacy}/dbg/Properties/AssemblyInfo.cs (100%) rename external/{cecil => cecil-legacy}/dbg/dbg.csproj (100%) create mode 100644 external/cecil-legacy/mono.snk rename external/{cecil => cecil-legacy}/rocks/.gitignore (100%) create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks.csproj create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/Functional.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/ILParser.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs create mode 100644 external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs rename external/{cecil => cecil-legacy}/rocks/Test/.gitignore (100%) create mode 100644 external/cecil-legacy/rocks/Test/Mono.Cecil.Rocks.Tests.csproj rename external/{cecil => cecil-legacy}/rocks/Test/Mono.Cecil.Tests/Addin.cs (100%) create mode 100644 external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs create mode 100644 external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs create mode 100644 external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs create mode 100644 external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeDefinitionRocksTests.cs create mode 100644 external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs create mode 100755 external/cecil-legacy/rocks/Test/Resources/cs/Types.cs rename external/{cecil => cecil-legacy}/symbols/mdb/.gitignore (100%) create mode 100644 external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb.csproj create mode 100644 external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs create mode 100644 external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs create mode 100644 external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs create mode 100644 external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs create mode 100644 external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs create mode 100644 external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs create mode 100644 external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs rename external/{cecil => cecil-legacy}/symbols/mdb/Test/.gitignore (100%) create mode 100644 external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj rename external/{cecil => cecil-legacy}/symbols/mdb/Test/Mono.Cecil.Tests/Addin.cs (100%) create mode 100644 external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs create mode 100644 external/cecil-legacy/symbols/mdb/Test/Resources/assemblies/hello.exe.mdb rename external/{cecil => cecil-legacy}/symbols/pdb/.gitignore (100%) create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitAccess.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitSet.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/CvInfo.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DataStream.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiDbgHdr.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiHeader.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiModuleInfo.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiSecCon.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/IntHashTable.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/Interfaces.cs create mode 100755 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/LICENSE create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/MsfDirectory.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbConstant.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbDebugException.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbException.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFile.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLine.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLines.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbReader.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbScope.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSlot.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSource.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbTokenLine.cs create mode 100644 external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/SourceLocationProvider.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb.csproj create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs create mode 100644 external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs rename external/{cecil => cecil-legacy}/symbols/pdb/Test/.gitignore (100%) create mode 100644 external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj rename external/{cecil => cecil-legacy}/symbols/pdb/Test/Mono.Cecil.Tests/Addin.cs (100%) rename external/{cecil => cecil-legacy}/symbols/pdb/Test/Mono.Cecil.Tests/Linq.cs (100%) create mode 100644 external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs create mode 100755 external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/VBConsApp.pdb create mode 100755 external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/fsapp.pdb create mode 100644 external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/test.pdb create mode 100644 external/cecil/.travis.yml create mode 100644 external/cecil/LICENSE.txt create mode 100644 external/cecil/Mono.Cecil.Cil/PortablePdb.cs create mode 100644 external/cecil/Mono.Cecil.Metadata/PdbHeap.cs create mode 100644 external/cecil/Mono.Cecil.Tests.props mode change 100755 => 100644 external/cecil/Mono.Cecil.nunit create mode 100644 external/cecil/Mono.Cecil.props mode change 100755 => 100644 external/cecil/Mono.Cecil.sln.DotSettings create mode 100644 external/cecil/Mono.Cecil/Treatments.cs create mode 100644 external/cecil/Mono.Cecil/WindowsRuntimeProjections.cs create mode 100644 external/cecil/Mono/Disposable.cs create mode 100644 external/cecil/Mono/Type.cs create mode 100644 external/cecil/ProjectInfo.cs create mode 100644 external/cecil/README.md create mode 100644 external/cecil/System.Security.Cryptography/SHA1Managed.cs create mode 100644 external/cecil/Test/Mono.Cecil.Tests/PortablePdbTests.cs create mode 100644 external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs create mode 100644 external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs create mode 100644 external/cecil/Test/Resources/assemblies/ManagedWinmd.winmd create mode 100644 external/cecil/Test/Resources/assemblies/NativeWinmd.winmd create mode 100644 external/cecil/Test/Resources/assemblies/PdbTarget.pdb create mode 100644 external/cecil/Test/Resources/assemblies/cecil.pdb.REMOVED.git-id create mode 100644 external/cecil/Test/Resources/assemblies/winrtcomp.winmd create mode 100644 external/cecil/Test/Resources/il/ca-empty-blob.il create mode 100644 external/cecil/Test/Resources/il/ca-iface-impl.il mode change 100755 => 100644 external/cecil/Test/libs/nunit-2.6.2/license.txt create mode 100644 external/cecil/appveyor.yml create mode 100644 external/cecil/core/.vscode/launch.json create mode 100644 external/cecil/core/.vscode/tasks.json create mode 100644 external/cecil/core/project.json create mode 100644 external/cecil/rocks/Mono.Cecil.Rocks/DocCommentId.cs create mode 100644 external/cecil/rocks/Test/Mono.Cecil.Tests/DocCommentIdTests.cs mode change 100755 => 100644 external/cecil/rocks/Test/Resources/cs/Types.cs create mode 100644 external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs create mode 100644 external/cecil/symbols/mdb/Test/Resources/assemblies/BreakpointTest.Portable.dll.mdb create mode 100644 external/cecil/symbols/mdb/Test/Resources/assemblies/mscorlib.dll.mdb.REMOVED.git-id mode change 100755 => 100644 external/cecil/symbols/pdb/Microsoft.Cci.Pdb/LICENSE create mode 100644 external/cecil/symbols/pdb/Test/Resources/assemblies/PdbTarget.pdb mode change 100755 => 100644 external/cecil/symbols/pdb/Test/Resources/assemblies/VBConsApp.pdb mode change 100755 => 100644 external/cecil/symbols/pdb/Test/Resources/assemblies/fsapp.pdb create mode 100644 external/nunit-lite/NUnitLite-1.0.0/src/framework/Assertion.cs create mode 100644 external/nunit-lite/NUnitLite-1.0.0/src/framework/StringAssert.cs create mode 100644 llvm/Makefile.am create mode 100644 llvm/Makefile.in create mode 100644 llvm/SUBMODULES.json create mode 100644 man/cert-sync.1 create mode 100644 mcs/class/Facades/System.Reflection.Emit.Lightweight/DynamicMethod.cs rename mcs/class/{Mono.Security.Providers.OldTls => Mono.Btls.Interface}/Makefile (58%) create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources rename mcs/class/{Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsContext.cs => Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs} (60%) create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs rename mcs/class/{Mono.Security/Mono.Security.Interface/IMonoTlsContext.cs => Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs} (57%) create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs rename mcs/class/{Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsConfiguration.cs => Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs} (76%) create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs rename mcs/class/{Mono.Security.Providers.DotNet => Mono.Btls.Interface}/Properties/AssemblyInfo.cs (88%) create mode 100644 mcs/class/Mono.CSharp/Test/Visit/ASTVisitorTest.cs create mode 100644 mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalScope.cs delete mode 100644 mcs/class/Mono.Security.Providers.DotNet/Makefile delete mode 100644 mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet.dll.sources delete mode 100644 mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetSslStreamImpl.cs delete mode 100644 mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetTlsProvider.cs delete mode 100644 mcs/class/Mono.Security.Providers.DotNet/README.md delete mode 100644 mcs/class/Mono.Security.Providers.NewSystemSource/Makefile delete mode 100644 mcs/class/Mono.Security.Providers.NewSystemSource/Mono.Security.Providers.NewSystemSource.dll.sources delete mode 100644 mcs/class/Mono.Security.Providers.NewSystemSource/Properties/AssemblyInfo.cs delete mode 100644 mcs/class/Mono.Security.Providers.NewSystemSource/README.md delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Makefile delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls.dll.sources delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStream.cs delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStreamFactory.cs delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/NewTlsProvider.cs delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsContextWrapper.cs delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsProviderFactory.cs delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/Properties/AssemblyInfo.cs delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/mobile_Mono.Security.Providers.NewTls.dll.sources delete mode 100644 mcs/class/Mono.Security.Providers.NewTls/mobile_static_Mono.Security.Providers.NewTls.dll.sources delete mode 100644 mcs/class/Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls/OldTlsProvider.cs create mode 100644 mcs/class/Mono.Tasklets/Mono.Tasklets_test.dll.sources create mode 100644 mcs/class/Mono.Tasklets/Test/Mono.Tasklets/ContinuationsTest.cs create mode 100644 mcs/class/System.Data/ReferenceSources/PoolBlockingPeriod.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlBulkCopy.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlCommand.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlCommandBuilder.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlConnection.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlDataReader.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlException.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlParameter.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlParameterCollection.platformnotsupported.cs create mode 100644 mcs/class/System.Data/System.Data.SqlClient/SqlTransaction.platformnotsupported.cs create mode 100644 mcs/class/System.Data/monotouch_watch_System.Data.dll.exclude.sources rename mcs/class/{System.ServiceModel => System.IdentityModel}/System.ServiceModel.Security.Tokens/BinarySecretSecurityToken.cs (100%) rename mcs/class/{System.ServiceModel => System.IdentityModel}/System.ServiceModel.Security.Tokens/InternalEncryptedKeyIdentifierClause.cs (100%) rename mcs/class/{System.ServiceModel => System.IdentityModel}/System.ServiceModel.Security.Tokens/WrappedKeySecurityToken.cs (100%) rename mcs/class/{System.ServiceModel => System.IdentityModel}/System.ServiceModel.Security/BinarySecretKeyIdentifierClause.cs (100%) rename mcs/class/{System.ServiceModel => System.IdentityModel}/System.ServiceModel.Security/KeyNameIdentifierClause.cs (100%) rename mcs/class/{System.ServiceModel => System.IdentityModel}/System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs (100%) create mode 100644 mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.platformnotsupported.cs create mode 100644 mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.exclude.sources create mode 100644 mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.sources delete mode 100644 mcs/class/System.Runtime.Caching/ReferenceSources/SRef.cs create mode 100644 mcs/class/System.Runtime.Serialization/ReferenceSources/LocalAppContextSwitches.cs create mode 100644 mcs/class/System.Runtime.Serialization/ReferenceSources/XsdDataContractExporter_mobile.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsBio.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsContext.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsError.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsException.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsKey.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsObject.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsProvider.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsSsl.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs rename mcs/class/System/{ReferenceSources/SSPIConfiguration.cs => Mono.Btls/MonoBtlsSslError.cs} (74%) create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsStream.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsUtils.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs rename mcs/class/{Mono.Security.Providers.OldTls/Properties/AssemblyInfo.cs => System/Mono.Btls/MonoBtlsX509LookupAndroid.cs} (65%) create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs create mode 100644 mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs create mode 100644 mcs/class/System/Mono.Btls/X509ChainImplBtls.cs rename mcs/class/System/Mono.Net.Security/{MonoLegacyTlsProvider.cs => LegacyTlsProvider.cs} (63%) delete mode 100644 mcs/class/System/Mono.Net.Security/MonoTlsProviderImpl.cs create mode 100644 mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs delete mode 100644 mcs/class/System/ReferenceSources/Internal.cs create mode 100644 mcs/class/System/ReferenceSources/LocalAppContextSwitches.cs create mode 100644 mcs/class/System/ReferenceSources/RequestCacheProtocol.cs delete mode 100644 mcs/class/System/ReferenceSources/SSPISafeHandles.cs delete mode 100644 mcs/class/System/ReferenceSources/SSPIWrapper.cs create mode 100644 mcs/class/System/ReferenceSources/SecureStringHelper.cs delete mode 100644 mcs/class/System/ReferenceSources/SslStream.cs delete mode 100644 mcs/class/System/ReferenceSources/SystemNetworkCredential.cs delete mode 100644 mcs/class/System/ReferenceSources/_SecureChannel.cs delete mode 100644 mcs/class/System/ReferenceSources/_SslState.cs delete mode 100644 mcs/class/System/ReferenceSources/_SslStream.cs delete mode 100644 mcs/class/System/System.Diagnostics/ProcessThreadCollection.cs create mode 100644 mcs/class/System/System.Net.Mail/SmtpClient.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net.Security/SslStream.platformnotsupported.cs rename mcs/class/{Facades => System}/System.Net.Sockets/SocketReceiveFromResult.cs (98%) rename mcs/class/{Facades => System}/System.Net.Sockets/SocketReceiveMessageFromResult.cs (98%) rename mcs/class/{Facades => System}/System.Net.Sockets/SocketTaskExtensions.cs (99%) create mode 100644 mcs/class/System/System.Net.Sockets/TcpClient.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net.WebSockets/ClientWebSocket.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/AuthenticationManager.platformnotsupported.cs delete mode 100644 mcs/class/System/System.Net/CredentialCache.cs rename mcs/class/{corlib/System.Diagnostics.Tracing/EventSourceException.cs => System/System.Net/FtpRequestCreator.platformnotsupported.cs} (74%) create mode 100644 mcs/class/System/System.Net/FtpWebRequest.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/FtpWebResponse.platformnotsupported.cs delete mode 100644 mcs/class/System/System.Net/GlobalProxySelection.cs create mode 100644 mcs/class/System/System.Net/HttpListener.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/HttpListenerPrefixCollection.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/HttpListenerRequest.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/HttpListenerResponse.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/HttpListenerResponseHelper.cs create mode 100644 mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/HttpWebResponse.platformnotsupported.cs delete mode 100644 mcs/class/System/System.Net/NetworkCredential.cs create mode 100644 mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs create mode 100644 mcs/class/System/System.Net/ServicePointManager.platformnotsupported.cs delete mode 100644 mcs/class/System/System.Net/WebProxy.cs delete mode 100644 mcs/class/System/System.Net/WebRequest.cs delete mode 100644 mcs/class/System/System.Threading/Semaphore.cs rename mcs/class/{Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls.dll.sources => System/monotouch_watch_System.dll.exclude.sources} (53%) create mode 100644 mcs/class/System/monotouch_watch_runtime_System.dll.exclude.sources create mode 100644 mcs/class/corlib/Mono/RuntimeHandles.cs create mode 100644 mcs/class/corlib/Mono/RuntimeMarshal.cs create mode 100644 mcs/class/corlib/Mono/RuntimeStructs.cs create mode 100644 mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs create mode 100644 mcs/class/corlib/Mono/SafeStringMarshal.cs create mode 100644 mcs/class/corlib/ReferenceSources/PathInternal.cs delete mode 100644 mcs/class/corlib/ReferenceSources/SharedStatics.cs rename mcs/class/{Facades => corlib}/System.Diagnostics.Tracing/EventCounter.cs (98%) create mode 100644 mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.pns.cs rename mcs/class/corlib/{System.Reflection/TargetParameterCountException.cs => System.Reflection.Emit/CustomAttributeBuilder.pns.cs} (53%) create mode 100644 mcs/class/corlib/System.Reflection.Emit/EnumBuilder.pns.cs rename mcs/class/corlib/{System.Reflection/TargetException.cs => System.Reflection.Emit/EventBuilder.pns.cs} (55%) rename mcs/class/{System/System.Diagnostics/ProcessModuleCollection.cs => corlib/System.Reflection.Emit/FieldBuilder.pns.cs} (50%) create mode 100644 mcs/class/corlib/System.Reflection.Emit/GenericTypeParameterBuilder.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/ILGenerator.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/MethodBuilder.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/ParameterBuilder.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/PropertyBuilder.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/SignatureHelper.pns.cs create mode 100644 mcs/class/corlib/System.Reflection.Emit/TypeBuilder.pns.cs rename mcs/class/corlib/System.Security.Cryptography/{CryptoConfig_2_1.cs => CryptoConfig.common.cs} (100%) rename mcs/class/{System.Core => corlib}/System.Security.Cryptography/IncrementalHash.cs (98%) delete mode 100644 mcs/class/corlib/System.Threading/EventWaitHandle.cs delete mode 100644 mcs/class/corlib/System/GC.cs create mode 100644 mcs/class/corlib/Test/System/GCTest.cs delete mode 100644 mcs/class/corlib/coreclr/AsyncLocal.cs delete mode 100644 mcs/class/corlib/coreclr/DisablePrivateReflectionAttribute.cs delete mode 100644 mcs/class/corlib/coreclr/EncodingProvider.cs delete mode 100644 mcs/class/corlib/coreclr/FormattableString.cs delete mode 100644 mcs/class/corlib/coreclr/FormattableStringFactory.cs delete mode 100644 mcs/class/corlib/coreclr/WaitHandleExtensions.cs create mode 100644 mcs/class/legacy/Mono.Cecil/Makefile create mode 100644 mcs/class/legacy/Mono.Cecil/Mono.Cecil.dll.sources delete mode 100644 mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs create mode 100644 mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs.REMOVED.git-id create mode 100644 mcs/errors/cs0029-37.cs create mode 100644 mcs/errors/cs0122-39.cs create mode 100644 mcs/errors/cs0177-15.cs create mode 100644 mcs/errors/cs0619-59.cs create mode 100644 mcs/errors/cs1070-3.cs create mode 100644 mcs/errors/cs1501-19.cs delete mode 100644 mcs/errors/cs1691-2.cs delete mode 100644 mcs/errors/cs1691-3.cs delete mode 100644 mcs/errors/cs1691-4.cs delete mode 100644 mcs/errors/cs1691.cs create mode 100644 mcs/errors/cs1744-3.cs delete mode 100644 mcs/errors/cs1904.cs create mode 100644 mcs/tests/gtest-638.cs create mode 100644 mcs/tests/gtest-639.cs create mode 100644 mcs/tests/test-937.cs create mode 100644 mcs/tests/test-940.cs create mode 100644 mcs/tests/test-941.cs create mode 100644 mcs/tests/test-debug-31-ref.xml create mode 100644 mcs/tests/test-debug-31.cs create mode 100644 mcs/tests/test-debug-32-ref.xml create mode 100644 mcs/tests/test-debug-32.cs create mode 100644 mcs/tests/test-named-10.cs create mode 100644 mcs/tests/test-partial-35.cs create mode 100644 mcs/tools/btls/AssemblyInfo.cs create mode 100644 mcs/tools/btls/Makefile create mode 100644 mcs/tools/btls/btls-cert-sync.cs create mode 100644 mcs/tools/btls/btls-cert-sync.exe.sources create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClassExtensions.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClassExtensions.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClassExtensions.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClassExtensions.xml create mode 100644 mcs/tools/mdoc/Test/en.expected-dropns-multi/MyFramework.MyNamespace/MyClassExtensions.xml create mode 100644 mono/btls/Makefile.am create mode 100644 mono/btls/Makefile.in delete mode 100644 mono/io-layer/handles-private.h delete mode 100644 mono/io-layer/handles.c delete mode 100644 mono/io-layer/handles.h delete mode 100644 mono/io-layer/thread-private.h delete mode 100644 mono/io-layer/threads.h create mode 100644 mono/io-layer/wapi.c delete mode 100644 mono/io-layer/wthreads.c delete mode 100644 mono/metadata/assembly.c create mode 100644 mono/metadata/assembly.c.REMOVED.git-id create mode 100644 mono/metadata/custom-attrs-internals.h create mode 100644 mono/metadata/custom-attrs.c create mode 100644 mono/metadata/dynamic-image-internals.h create mode 100644 mono/metadata/dynamic-image.c create mode 100644 mono/metadata/dynamic-stream-internals.h create mode 100644 mono/metadata/dynamic-stream.c create mode 100644 mono/metadata/reflection-cache.h create mode 100644 mono/metadata/reflection.c delete mode 100644 mono/metadata/reflection.c.REMOVED.git-id create mode 100644 mono/metadata/sgen-dynarray.h create mode 100644 mono/metadata/sre-encode.c create mode 100644 mono/metadata/sre-internals.h create mode 100644 mono/metadata/sre-save.c.REMOVED.git-id create mode 100644 mono/metadata/sre.c.REMOVED.git-id delete mode 100755 mono/mini/emitnunit.pl create mode 100644 mono/mini/mini-windows-dllmain.c delete mode 100644 mono/profiler/decode.c.REMOVED.git-id create mode 100644 mono/profiler/mono-profiler-log.c.REMOVED.git-id rename mono/profiler/{proflog.h => mono-profiler-log.h} (99%) create mode 100644 mono/profiler/mprof-report.c.REMOVED.git-id delete mode 100644 mono/profiler/proflog.c.REMOVED.git-id delete mode 100644 mono/profiler/utils.c delete mode 100644 mono/profiler/utils.h create mode 100644 mono/tests/abort-cctor.cs delete mode 100644 mono/tests/appdomain-async-invoke.cs delete mode 100644 mono/tests/appdomain-client.cs delete mode 100644 mono/tests/appdomain-exit.cs delete mode 100644 mono/tests/appdomain-thread-abort.cs delete mode 100644 mono/tests/appdomain-unload-callback.cs delete mode 100644 mono/tests/appdomain-unload-doesnot-raise-pending-events.cs delete mode 100644 mono/tests/appdomain-unload.cs delete mode 100644 mono/tests/appdomain.cs delete mode 100644 mono/tests/appdomain1.cs delete mode 100644 mono/tests/appdomain2.cs delete mode 100644 mono/tests/assembly_append_ordering.cs delete mode 100644 mono/tests/assemblyresolve_event2.2.cs delete mode 100644 mono/tests/bug-322722_dyn_method_throw.2.cs delete mode 100644 mono/tests/bug-322722_patch_bx.2.cs delete mode 100644 mono/tests/bug-333798-tb.2.cs delete mode 100644 mono/tests/bug-335131.2.cs delete mode 100644 mono/tests/bug-349190.2.cs delete mode 100644 mono/tests/bug-36848.cs delete mode 100644 mono/tests/bug-389886-2.cs delete mode 100644 mono/tests/bug-389886-3.cs delete mode 100644 mono/tests/bug-389886-sre-generic-interface-instances.cs delete mode 100644 mono/tests/bug-462592.cs delete mode 100644 mono/tests/bug-47295.cs delete mode 100644 mono/tests/bug-48015.cs delete mode 100644 mono/tests/bug-515884.il delete mode 100644 mono/tests/bug-544446.cs delete mode 100644 mono/tests/bug-575941.cs delete mode 100644 mono/tests/bug-80307.cs delete mode 100644 mono/tests/cominterop.cs delete mode 100644 mono/tests/constraints-load.il delete mode 100644 mono/tests/cross-domain.cs delete mode 100644 mono/tests/delegate9.cs delete mode 100644 mono/tests/dynamic-generic-size.cs delete mode 100644 mono/tests/dynamic-method-access.2.cs delete mode 100644 mono/tests/dynamic-method-finalize.2.cs delete mode 100644 mono/tests/dynamic-method-resurrection.cs delete mode 100644 mono/tests/dynamic-method-stack-traces.cs delete mode 100644 mono/tests/generic-marshalbyref.2.cs delete mode 100644 mono/tests/generic-type-builder.2.cs delete mode 100644 mono/tests/generic-unloading.2.cs delete mode 100644 mono/tests/generic-xdomain.2.cs delete mode 100644 mono/tests/generic_type_definition.2.cs delete mode 100644 mono/tests/loader.cs delete mode 100644 mono/tests/marshal-valuetypes.cs delete mode 100644 mono/tests/monitor.cs delete mode 100644 mono/tests/pinvoke2.cs create mode 100644 mono/tests/priority.cs create mode 100644 mono/tests/reference-loader.cs delete mode 100644 mono/tests/remoting1.cs delete mode 100644 mono/tests/remoting2.cs delete mode 100644 mono/tests/remoting3.cs delete mode 100644 mono/tests/remoting5.cs delete mode 100644 mono/tests/stackframes-async.2.cs delete mode 100644 mono/tests/thread6.cs delete mode 100644 mono/tests/threadpool-exceptions7.cs delete mode 100644 mono/tests/transparentproxy.cs delete mode 100644 mono/tests/unload-appdomain-on-shutdown.cs delete mode 100644 mono/tests/xdomain-threads.cs create mode 100644 mono/utils/mono-log-android.c create mode 100644 mono/utils/mono-log-common.c create mode 100644 mono/utils/mono-log-darwin.c create mode 100644 mono/utils/mono-log-posix.c create mode 100644 mono/utils/mono-log-windows.c create mode 100644 mono/utils/mono-threads-netbsd.c create mode 100644 mono/utils/w32handle.c create mode 100644 mono/utils/w32handle.h create mode 100644 msvc/build-all.vcxproj create mode 100644 msvc/build-init.vcxproj create mode 100644 msvc/build-install.vcxproj create mode 100644 msvc/build-package.vcxproj create mode 100644 msvc/libgcmonosgen.vcxproj create mode 100644 msvc/libmono-static.vcxproj create mode 100644 msvc/mono-full-aot-compile-test.vcxproj create mode 100644 msvc/mono-full-aot-run-test.vcxproj create mode 100644 msvc/mono-mini-regression-test.vcxproj create mode 100644 msvc/mono-nunit-test.vcxproj create mode 100644 msvc/mono-testdriver-test.vcxproj create mode 100644 tools/pedump/Makefile.am create mode 100644 tools/pedump/Makefile.in rename {mono/metadata => tools/pedump}/pedump.c (99%) create mode 100644 tools/sgen/sgen-entry-stream.h create mode 100644 tools/sgen/sgen-grep-binprot.h diff --git a/Makefile.am b/Makefile.am index 5afacfa7fc..aaffb9842b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,18 +4,17 @@ AM_CFLAGS = $(WERROR_CFLAGS) MONOTOUCH_SUBDIRS = $(libgc_dir) eglib/src mono +# Some tools might not build when cross-compiling if CROSS_COMPILING -SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests -# Keep in sync with SUBDIRS -## 'tools' is not normally built -DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests +tools_dir = else -SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests -# Keep in sync with SUBDIRS -## 'tools' is not normally built -DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests +tools_dir = tools endif +SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples $(tools_dir) msvc $(docs_dir) acceptance-tests llvm +# Keep in sync with SUBDIRS +DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests llvm + all: update_submodules SUBMODULE_ERROR='Could not recursively update all git submodules. You may experience compilation problems if some submodules are out of date' @@ -68,6 +67,14 @@ get-monolite-latest: cd $(mcslib) && { (wget -O- $(monolite_url) || curl $(monolite_url)) | gzip -d | tar xf - ; } cd $(mcslib) && mv -f monolite-* monolite +if BITCODE +BITCODE_CHECK=yes +endif + +.PHONY: check-ci +check-ci: + MONO_LLVMONLY=$(BITCODE_CHECK) $(srcdir)/scripts/ci/run-test-$(TEST_PROFILE).sh + .PHONY: validate do-build-mono-mcs mcs-do-clean mcs-do-tests validate: do-build-mono-mcs $(MAKE) mcs-do-tests @@ -153,6 +160,7 @@ package-inputs: read libou; echo " $$libou"; \ read fx_ver; echo " $$fx_ver"; \ read profile; echo " $$profile"; \ + read resxt; echo " $$resxt"; \ read resp; echo " $$resp"; \ echo " ") >> msvc/scripts/order.xml; \ done diff --git a/Makefile.in b/Makefile.in index 060e2374c9..152dedfc88 100644 --- a/Makefile.in +++ b/Makefile.in @@ -205,6 +205,8 @@ distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -213,6 +215,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -222,6 +229,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -242,7 +250,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -257,10 +264,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -307,6 +316,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -316,6 +326,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -407,12 +418,13 @@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = $(WERROR_CFLAGS) MONOTOUCH_SUBDIRS = $(libgc_dir) eglib/src mono -@CROSS_COMPILING_FALSE@SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests -@CROSS_COMPILING_TRUE@SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests +@CROSS_COMPILING_FALSE@tools_dir = tools + +# Some tools might not build when cross-compiling +@CROSS_COMPILING_TRUE@tools_dir = +SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples $(tools_dir) msvc $(docs_dir) acceptance-tests llvm # Keep in sync with SUBDIRS -@CROSS_COMPILING_FALSE@DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests -# Keep in sync with SUBDIRS -@CROSS_COMPILING_TRUE@DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests +DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests llvm SUBMODULE_ERROR = 'Could not recursively update all git submodules. You may experience compilation problems if some submodules are out of date' EXTRA_DIST = \ README.md \ @@ -437,6 +449,7 @@ mcslib = $(mcs_topdir)/class/lib monolite = $(mcslib)/monolite mono_corlib_version = $(shell sed -n "s/\#define MONO_CORLIB_VERSION //p" $(srcdir)/mono/metadata/appdomain.c) monolite_url = http://download.mono-project.com/monolite/monolite-$(mono_corlib_version)-latest.tar.gz +@BITCODE_TRUE@BITCODE_CHECK = yes all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -949,6 +962,10 @@ get-monolite-latest: cd $(mcslib) && { (wget -O- $(monolite_url) || curl $(monolite_url)) | gzip -d | tar xf - ; } cd $(mcslib) && mv -f monolite-* monolite +.PHONY: check-ci +check-ci: + MONO_LLVMONLY=$(BITCODE_CHECK) $(srcdir)/scripts/ci/run-test-$(TEST_PROFILE).sh + .PHONY: validate do-build-mono-mcs mcs-do-clean mcs-do-tests validate: do-build-mono-mcs $(MAKE) mcs-do-tests @@ -1031,6 +1048,7 @@ package-inputs: read libou; echo " $$libou"; \ read fx_ver; echo " $$fx_ver"; \ read profile; echo " $$profile"; \ + read resxt; echo " $$resxt"; \ read resp; echo " $$resp"; \ echo " ") >> msvc/scripts/order.xml; \ done diff --git a/acceptance-tests/Makefile.am b/acceptance-tests/Makefile.am index 522cb36c9e..c03adcc0c4 100644 --- a/acceptance-tests/Makefile.am +++ b/acceptance-tests/Makefile.am @@ -1,4 +1,5 @@ ACCEPTANCE_TESTS_PATH=external +BENCHMARKER_PATH=$(ACCEPTANCE_TESTS_PATH)/benchmarker ROSLYN_PATH=$(ACCEPTANCE_TESTS_PATH)/roslyn CORECLR_PATH=$(ACCEPTANCE_TESTS_PATH)/coreclr MSTESTSUITE_PATH=$(ACCEPTANCE_TESTS_PATH)/ms-test-suite @@ -14,10 +15,11 @@ MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe ILASM = $(RUNTIME) $(CLASS)/ilasm.exe include versions.mk +include profiler-stress.mk include roslyn.mk include coreclr.mk include ms-test-suite.mk -check-full: check-roslyn check-coreclr check-ms-test-suite +check-full: check-profiler-stress check-roslyn check-coreclr check-ms-test-suite clean-local: clean-local-coreclr diff --git a/acceptance-tests/Makefile.in.REMOVED.git-id b/acceptance-tests/Makefile.in.REMOVED.git-id index c147f722f7..1e5f706790 100644 --- a/acceptance-tests/Makefile.in.REMOVED.git-id +++ b/acceptance-tests/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -32956102bf8b153420545562e9066c249e538001 \ No newline at end of file +61a884697b79e16cc9e036de2b08a7e79166e5ac \ No newline at end of file diff --git a/acceptance-tests/SUBMODULES.json b/acceptance-tests/SUBMODULES.json index 7fcac6c3e9..01faee39c9 100644 --- a/acceptance-tests/SUBMODULES.json +++ b/acceptance-tests/SUBMODULES.json @@ -18,9 +18,17 @@ { "name": "ms-test-suite", "url": "git@github.com:xamarin/ms-test-suite.git", - "rev": "840653918efed24f00f5e166094f06354cae7255", + "rev": "eb7cd709549bffe170653a50805f1593d66ea81e", "remote-branch": "origin/master", "branch": "master", "directory": "ms-test-suite" + }, + { + "name": "benchmarker", + "url": "git://github.com/xamarin/benchmarker.git", + "rev": "97f618cd585af549dd861b7c142656c496f6a89b", + "remote-branch": "origin/master", + "branch": "master", + "directory": "benchmarker" } -] \ No newline at end of file +] diff --git a/acceptance-tests/coreclr.mk.REMOVED.git-id b/acceptance-tests/coreclr.mk.REMOVED.git-id index 816e6b2a14..e8a38be67e 100644 --- a/acceptance-tests/coreclr.mk.REMOVED.git-id +++ b/acceptance-tests/coreclr.mk.REMOVED.git-id @@ -1 +1 @@ -8f75b05470fe46685d232f3a35933dbc1080fc59 \ No newline at end of file +1f4be3d1e8fbc9cefb15d72648b5068298d01356 \ No newline at end of file diff --git a/acceptance-tests/ms-test-suite.mk b/acceptance-tests/ms-test-suite.mk index c1c1619948..bd85bd494b 100644 --- a/acceptance-tests/ms-test-suite.mk +++ b/acceptance-tests/ms-test-suite.mk @@ -1,10 +1,10 @@ check-ms-test-suite: @if $(MAKE) validate-ms-test-suite RESET_VERSIONS=1; then \ - $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -t:library -warn:1 -r:nunit.framework" && \ + $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -debug -t:library -warn:1 -r:nunit.framework" && \ $(MAKE) -C $(MSTESTSUITE_PATH)/conformance run NUNIT-CONSOLE="$(RUNTIME) $(CLASS)/nunit-console.exe -nologo -exclude=MonoBug,BadTest" NUNIT_XML_RESULT=$(abs_top_builddir)/acceptance-tests/TestResult-ms-test-suite-conformance.xml || EXIT_CODE=1; \ $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup build MCS="$(MCS) -debug -warn:1" && \ $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup run MONO="$(RUNTIME)" || EXIT_CODE=1; \ exit $$EXIT_CODE; \ else \ echo "*** [ms-test-suite] Getting the repository failed, you probably don't have access to this Xamarin-internal resource. Skipping."; \ - fi \ No newline at end of file + fi diff --git a/acceptance-tests/profiler-stress.mk b/acceptance-tests/profiler-stress.mk new file mode 100644 index 0000000000..ff67772a1d --- /dev/null +++ b/acceptance-tests/profiler-stress.mk @@ -0,0 +1,13 @@ +SYS_REFS = \ + System.dll \ + System.Core.dll \ + System.Data.dll \ + System.Runtime.Serialization.dll \ + System.Xml.dll \ + System.Xml.Linq.dll \ + Mono.Posix.dll + +check-profiler-stress: + @$(MAKE) validate-benchmarker RESET_VERSIONS=1 + cd profiler-stress && $(MCS) -target:exe $(addprefix -r:, $(SYS_REFS)) -out:runner.exe @runner.exe.sources + cd profiler-stress && $(RUNTIME) runner.exe diff --git a/acceptance-tests/roslyn.mk b/acceptance-tests/roslyn.mk index fbfa2760ec..a91c68d986 100644 --- a/acceptance-tests/roslyn.mk +++ b/acceptance-tests/roslyn.mk @@ -4,17 +4,11 @@ check-roslyn: sed -i -e 's/\\4.5-api"/\\4.5"/g' $$PREFIX/lib/mono/xbuild-frameworks/.NETFramework/v4.5/RedistList/FrameworkList.xml; \ export MSBuildExtensionsPath=$$PREFIX/lib/mono/xbuild; \ MONO_DOTNET_PORTABLE_DIR=$$PREFIX/lib/mono/xbuild-frameworks/.NETPortable/; \ - MONO_NUGET_TARGETS_DIR=$$PREFIX/lib/mono/xbuild/Microsoft/NuGet/; \ - MONO_PORTABLE_TARGETS_DIR=$$PREFIX/lib/mono/xbuild/Microsoft/Portable/v5.0; \ - if [ ! -d "$$MONO_DOTNET_PORTABLE_DIR/v5.0" ]; then \ + if [ ! -d "$$MONO_DOTNET_PORTABLE_DIR/v4.6" ]; then \ mkdir -p $$MONO_DOTNET_PORTABLE_DIR; \ - mkdir -p $$MONO_NUGET_TARGETS_DIR; \ - mkdir -p $$MONO_PORTABLE_TARGETS_DIR; \ curl -SL "http://download.mono-project.com/third-party/RoslynBuildDependencies.zip" > /tmp/RoslynBuildDependencies.zip; \ unzip -o /tmp/RoslynBuildDependencies.zip -d /tmp/RoslynBuildDependencies; \ cp -r /tmp/RoslynBuildDependencies/PortableReferenceAssemblies/* $$MONO_DOTNET_PORTABLE_DIR; \ - cp /tmp/RoslynBuildDependencies/NuGetTargets/* $$MONO_NUGET_TARGETS_DIR; \ - cp /tmp/RoslynBuildDependencies/PortableTargets/* $$MONO_PORTABLE_TARGETS_DIR; \ fi; \ cd $(ROSLYN_PATH); \ sed -i -e 'N; s/bootstrapArg=".*\n.*"/bootstrapArg=""/g' cibuild.sh; \ diff --git a/acceptance-tests/versions.mk b/acceptance-tests/versions.mk index 84b4f85c6c..0c070a0f11 100644 --- a/acceptance-tests/versions.mk +++ b/acceptance-tests/versions.mk @@ -3,28 +3,35 @@ SUBMODULES_CONFIG_FILE = $(top_srcdir)/acceptance-tests/SUBMODULES.json include $(top_srcdir)/scripts/submodules/versions.mk +$(eval $(call ValidateVersionTemplate,benchmarker,BENCHMARKER)) $(eval $(call ValidateVersionTemplate,roslyn,ROSLYN)) $(eval $(call ValidateVersionTemplate,coreclr,CORECLR)) $(eval $(call ValidateVersionTemplate,ms-test-suite,MSTESTSUITE)) # Bump the given submodule to the revision given by the REV make variable # If COMMIT is 1, commit the change +bump-benchmarker: __bump-benchmarker bump-roslyn: __bump-version-roslyn bump-coreclr: __bump-version-coreclr bump-ms-test-suite: __bump-version-ms-test-suite # Bump the given submodule to the branch given by the BRANCH/REMOTE_BRANCH make variables # If COMMIT is 1, commit the change +bump-branch-benchmarker: __bump-branch-benchmarker bump-branch-roslyn: __bump-branch-roslyn bump-branch-coreclr: __bump-branch-coreclr bump-branch-ms-test-suite: __bump-branch-ms-test-suite # Bump the given submodule to its current GIT version # If COMMIT is 1, commit the change +bump-current-benchmarker: __bump-current-benchmarker bump-current-roslyn: __bump-current-version-roslyn bump-current-coreclr: __bump-current-version-coreclr bump-current-ms-test-suite: __bump-current-version-ms-test-suite +commit-bump-benchmarker: + $(MAKE) bump-benchmarker COMMIT=1 + commit-bump-roslyn: $(MAKE) bump-roslyn COMMIT=1 @@ -34,6 +41,9 @@ commit-bump-coreclr: commit-bump-ms-test-suite: $(MAKE) bump-ms-test-suite COMMIT=1 +commit-bump-current-benchmarker: + $(MAKE) bump-current-benchmarker COMMIT=1 + commit-bump-current-roslyn: $(MAKE) bump-current-roslyn COMMIT=1 diff --git a/autogen.sh b/autogen.sh index 5607051074..2fe9281e8d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -160,8 +160,9 @@ if test -d $srcdir/eglib; then echo Done running eglib/autogen.sh ... fi - -echo "MONO_EXTRA_CONFIGURE_FLAGS is $MONO_EXTRA_CONFIGURE_FLAGS" +if test x$MONO_EXTRA_CONFIGURE_FLAGS != x; then + echo "MONO_EXTRA_CONFIGURE_FLAGS is $MONO_EXTRA_CONFIGURE_FLAGS" +fi conf_flags="$MONO_EXTRA_CONFIGURE_FLAGS --enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c diff --git a/config.h.in b/config.h.in index f2bcdd2b43..3784a123c9 100644 --- a/config.h.in +++ b/config.h.in @@ -142,9 +142,6 @@ /* Runtime support code for llvm enabled */ #undef ENABLE_LLVM_RUNTIME -/* Enable using `perf` for profiling on Linux */ -#undef ENABLE_PERF_EVENTS - /* Have GLIBC_BEFORE_2_3_4_SCHED_SETAFFINITY */ #undef GLIBC_BEFORE_2_3_4_SCHED_SETAFFINITY @@ -187,6 +184,9 @@ /* Define to 1 if the system has the type `blksize_t'. */ #undef HAVE_BLKSIZE_T +/* BoringTls is supported */ +#undef HAVE_BTLS + /* Define to 1 if you have the header file. */ #undef HAVE_CHECKLIST_H @@ -257,6 +257,9 @@ /* dlopen-based dynamic loader available */ #undef HAVE_DL_LOADER +/* BTLS in a shared libraty */ +#undef HAVE_DYNAMIC_BTLS + /* Define to 1 if you have the header file. */ #undef HAVE_ELF_H diff --git a/configure.REMOVED.git-id b/configure.REMOVED.git-id index bea139836e..1c7887c91f 100644 --- a/configure.REMOVED.git-id +++ b/configure.REMOVED.git-id @@ -1 +1 @@ -e8e55390c7a19b75beced76b13cba26115783992 \ No newline at end of file +ce2dd70081b10fc07545b674f66612013c842eb7 \ No newline at end of file diff --git a/configure.ac.REMOVED.git-id b/configure.ac.REMOVED.git-id index d6f664fe20..dc73251f27 100644 --- a/configure.ac.REMOVED.git-id +++ b/configure.ac.REMOVED.git-id @@ -1 +1 @@ -249f69974e9846cf3b2f1ea6d1abcb79faff896f \ No newline at end of file +fa5977bb752c6bb7aa22669e6857d309df993ed3 \ No newline at end of file diff --git a/data/Makefile.in b/data/Makefile.in index 7a8842532c..16bda6b6e2 100644 --- a/data/Makefile.in +++ b/data/Makefile.in @@ -228,6 +228,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -236,6 +238,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -245,6 +252,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -265,7 +273,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -280,10 +287,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -330,6 +339,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -339,6 +349,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/config.in b/data/config.in index b4b7243ecf..be83151429 100644 --- a/data/config.in +++ b/data/config.in @@ -11,6 +11,7 @@ + diff --git a/data/net_2_0/Browsers/Makefile.in b/data/net_2_0/Browsers/Makefile.in index 337423c49e..b514be21f8 100644 --- a/data/net_2_0/Browsers/Makefile.in +++ b/data/net_2_0/Browsers/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_2_0/Makefile.in b/data/net_2_0/Makefile.in index ac2dc9dcfd..fa6361a8d9 100644 --- a/data/net_2_0/Makefile.in +++ b/data/net_2_0/Makefile.in @@ -210,6 +210,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -218,6 +220,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -227,6 +234,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -247,7 +255,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -262,10 +269,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -312,6 +321,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -321,6 +331,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_0/Browsers/Makefile.in b/data/net_4_0/Browsers/Makefile.in index 7a00977e8c..eb112e758b 100644 --- a/data/net_4_0/Browsers/Makefile.in +++ b/data/net_4_0/Browsers/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_0/Makefile.in b/data/net_4_0/Makefile.in index da4d0e9404..23828d4665 100644 --- a/data/net_4_0/Makefile.in +++ b/data/net_4_0/Makefile.in @@ -210,6 +210,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -218,6 +220,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -227,6 +234,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -247,7 +255,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -262,10 +269,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -312,6 +321,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -321,6 +331,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_5/Browsers/Makefile.in b/data/net_4_5/Browsers/Makefile.in index ea0e8ac234..f39432d05d 100644 --- a/data/net_4_5/Browsers/Makefile.in +++ b/data/net_4_5/Browsers/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_5/Makefile.in b/data/net_4_5/Makefile.in index f62c70b756..e68780a1ca 100644 --- a/data/net_4_5/Makefile.in +++ b/data/net_4_5/Makefile.in @@ -210,6 +210,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -218,6 +220,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -227,6 +234,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -247,7 +255,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -262,10 +269,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -312,6 +321,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -321,6 +331,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/docs/Makefile.in b/docs/Makefile.in index 5aa48f48d0..5e461cfcd6 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/docs/deploy/mono-api-gc.html b/docs/deploy/mono-api-gc.html index 9b85a5194b..e51976f564 100644 --- a/docs/deploy/mono-api-gc.html +++ b/docs/deploy/mono-api-gc.html @@ -498,9 +498,8 @@ mono_gc_reference_queue_new (mono_reference_queue_callback callback)

The output of the SCC analysis is passed to the `cross_references()` callback. It is expected to set the `is_alive` flag on those strongly connected components that it - wishes to be kept alive. Only bridged objects will be - reported to the callback, i.e., non-bridged objects are - removed from the callback graph. + wishes to be kept alive. The value of `is_alive` will be + ignored on any SCCs which lack bridges.

In monodroid each bridged object has a corresponding Java mirror object. In the bridge callback it reifies the Mono @@ -521,7 +520,7 @@ mono_gc_reference_queue_new (mono_reference_queue_callback callback)

enum { - SGEN_BRIDGE_VERSION = 4 + SGEN_BRIDGE_VERSION = 5 }; typedef enum { diff --git a/docs/deploy/mono-api-internal.html b/docs/deploy/mono-api-internal.html index 7e94ca2974..48d4f690f9 100644 --- a/docs/deploy/mono-api-internal.html +++ b/docs/deploy/mono-api-internal.html @@ -532,8 +532,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
method The MonoMethod to wrap.
check_exceptions Whenever to check for pending exceptions
Description

generates IL code for the pinvoke wrapper (the generated method - calls the unmanaged code in piinfo->addr) - The wrapper info for the wrapper is a WrapperInfo structure.

+ calls the unmanaged code in piinfo->addr)
@@ -570,8 +569,7 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass)
Parameters
klass
Description

- generates IL code for PtrToStructure (IntPtr src, object structure) - The wrapper info for the wrapper is a WrapperInfo structure.

+ generates IL code for PtrToStructure (IntPtr src, object structure) @@ -698,8 +696,7 @@ mono_marshal_get_struct_to_ptr (MonoClass *klass)
Parameters
klass
Description

- generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld) - The wrapper info for the wrapper is a WrapperInfo structure.

+ generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld) diff --git a/docs/deploy/mono-api-unsorted.html b/docs/deploy/mono-api-unsorted.html index a2a1496a6b..b7d320d32a 100644 --- a/docs/deploy/mono-api-unsorted.html +++ b/docs/deploy/mono-api-unsorted.html @@ -293,7 +293,7 @@ mono_dllmap_insert (MonoImage *assembly, const char *dll, const char *func, cons

Parameters
-
assembly if NULL, this is a global mapping, otherwise the remapping of the dynamic library will only apply to the specified assembly
dll The name of the external library, as it would be found in the DllImport declaration. If prefixed with 'i:' the matching of the library name is done without case sensitivity
func if not null, the mapping will only applied to the named function (the value of EntryPoint)
tdll The name of the library to map the specified dll if it matches.
tfunc if func is not NULL, the name of the function that replaces the invocation
Description
+
assembly if NULL, this is a global mapping, otherwise the remapping of the dynamic library will only apply to the specified assembly
dll The name of the external library, as it would be found in the DllImport declaration. If prefixed with 'i:' the matching of the library name is done without case sensitivity
func if not null, the mapping will only applied to the named function (the value of EntryPoint)
tdll The name of the library to map the specified dll if it matches.
tfunc The name of the function that replaces the invocation. If NULL, it is replaced with a copy of func.
Description

LOCKING: Acquires the loader lock.

diff --git a/docs/deploy/mono-api-wapi.html.REMOVED.git-id b/docs/deploy/mono-api-wapi.html.REMOVED.git-id index e32914e3b5..4b5116790f 100644 --- a/docs/deploy/mono-api-wapi.html.REMOVED.git-id +++ b/docs/deploy/mono-api-wapi.html.REMOVED.git-id @@ -1 +1 @@ -3e44f606f7cee10fd72df9399ead2393fe7e824c \ No newline at end of file +dc9f5d8b06210d860035b42ede58f35b8e7c32bd \ No newline at end of file diff --git a/docs/sources/mono-api-gc.html b/docs/sources/mono-api-gc.html index 20d6cb9dc9..cddef0364c 100644 --- a/docs/sources/mono-api-gc.html +++ b/docs/sources/mono-api-gc.html @@ -40,9 +40,8 @@

The output of the SCC analysis is passed to the `cross_references()` callback. It is expected to set the `is_alive` flag on those strongly connected components that it - wishes to be kept alive. Only bridged objects will be - reported to the callback, i.e., non-bridged objects are - removed from the callback graph. + wishes to be kept alive. The value of `is_alive` will be + ignored on any SCCs which lack bridges.

In monodroid each bridged object has a corresponding Java mirror object. In the bridge callback it reifies the Mono @@ -63,7 +62,7 @@

enum { - SGEN_BRIDGE_VERSION = 4 + SGEN_BRIDGE_VERSION = 5 }; typedef enum { diff --git a/eglib/config.h.in b/eglib/config.h.in index 983d93f90c..101a0b179a 100644 --- a/eglib/config.h.in +++ b/eglib/config.h.in @@ -3,6 +3,9 @@ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD +/* Overridable allocator support enabled */ +#undef ENABLE_OVERRIDABLE_ALLOCATORS + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H diff --git a/eglib/configure.REMOVED.git-id b/eglib/configure.REMOVED.git-id index 438fece81b..55fa39a2b8 100644 --- a/eglib/configure.REMOVED.git-id +++ b/eglib/configure.REMOVED.git-id @@ -1 +1 @@ -e6c748208dd33485e04939f7cbb59545aa05f3a3 \ No newline at end of file +801fdd9c4cde828e7e92456ad7de345487765e0b \ No newline at end of file diff --git a/eglib/configure.ac b/eglib/configure.ac index 7622701ef4..a33dcb846b 100644 --- a/eglib/configure.ac +++ b/eglib/configure.ac @@ -138,6 +138,15 @@ AC_CHECK_FUNCS(strlcpy stpcpy strtok_r rewinddir vasprintf) AC_CHECK_FUNCS(getrlimit) AC_CHECK_FUNCS(fork execv execve) +AC_ARG_WITH([overridable-allocators], [ --with-overridable-allocators allow g_*alloc/g_free to call custom allocators set via g_mem_set_vtable]) + +if test x$with_overridable_allocators = xyes; then + AC_DEFINE(ENABLE_OVERRIDABLE_ALLOCATORS,1,[Overridable allocator support enabled]) + AC_MSG_NOTICE([Overridable allocator support enabled]) +else + AC_MSG_NOTICE([Overridable allocator support disabled]) +fi + # # Mono currently supports 10.6, but strndup is not available prior to 10.7; avoiding # the detection of strndup on OS X so Mono built on 10.7+ still runs on 10.6. This can be @@ -151,7 +160,7 @@ elif test x$target_ios = xno; then AC_CHECK_FUNCS(strndup getpwuid_r) fi -AM_CONDITIONAL(NEED_VASPRINTF, test x$ac_cv_func_vasprintf = xno ) +AM_CONDITIONAL(NEED_VASPRINTF, test x$ac_cv_func_vasprintf = xno || test x$with_overridable_allocators = xyes) AM_ICONV() AC_SEARCH_LIBS(sqrtf, m) diff --git a/eglib/src/Makefile.am b/eglib/src/Makefile.am index 31771dfd9a..1527ba26d3 100644 --- a/eglib/src/Makefile.am +++ b/eglib/src/Makefile.am @@ -11,14 +11,6 @@ unix_files = \ gdate-unix.c gdir-unix.c gfile-unix.c gmisc-unix.c \ gmodule-unix.c gtimer-unix.c -# some unices and windows do not have an implementation of vasprintf -# used by eglib, use provided implementation instead -if NEED_VASPRINTF -vasprintf_files = vasprintf.c -else -vaprinttf_files = foo.c -endif - if HOST_WIN32 os_files = $(win_files) else @@ -32,7 +24,6 @@ libeglib_la_SOURCES = \ garray.c \ gbytearray.c \ gerror.c \ - vasprintf.h \ ghashtable.c \ giconv.c \ gmem.c \ @@ -55,8 +46,7 @@ libeglib_la_SOURCES = \ gutf8.c \ gunicode.c \ unicode-data.h \ - $(os_files) \ - $(vasprintf_files) + $(os_files) libeglib_la_CFLAGS = -g -Wall -D_FORTIFY_SOURCE=2 diff --git a/eglib/src/Makefile.in b/eglib/src/Makefile.in index ba0d1db216..61edfd331a 100644 --- a/eglib/src/Makefile.in +++ b/eglib/src/Makefile.in @@ -100,14 +100,14 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = @HOST_WIN32_TRUE@libeglib_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__libeglib_la_SOURCES_DIST = eglib-remap.h sort.frag.h glib.h \ - garray.c gbytearray.c gerror.c vasprintf.h ghashtable.c \ - giconv.c gmem.c gmodule.h goutput.c gqsort.c gstr.c gslist.c \ - gstring.c gptrarray.c glist.c gqueue.c gpath.c gshell.c \ - gspawn.c gfile.c gfile-posix.c gpattern.c gmarkup.c gutf8.c \ - gunicode.c unicode-data.h gdate-unix.c gdir-unix.c \ - gfile-unix.c gmisc-unix.c gmodule-unix.c gtimer-unix.c \ - eglib-config.hw gdate-win32.c gdir-win32.c gfile-win32.c \ - gmisc-win32.c gmodule-win32.c gtimer-win32.c vasprintf.c + garray.c gbytearray.c gerror.c ghashtable.c giconv.c gmem.c \ + gmodule.h goutput.c gqsort.c gstr.c gslist.c gstring.c \ + gptrarray.c glist.c gqueue.c gpath.c gshell.c gspawn.c gfile.c \ + gfile-posix.c gpattern.c gmarkup.c gutf8.c gunicode.c \ + unicode-data.h gdate-unix.c gdir-unix.c gfile-unix.c \ + gmisc-unix.c gmodule-unix.c gtimer-unix.c eglib-config.hw \ + gdate-win32.c gdir-win32.c gfile-win32.c gmisc-win32.c \ + gmodule-win32.c gtimer-win32.c am__objects_1 = libeglib_la-gdate-unix.lo libeglib_la-gdir-unix.lo \ libeglib_la-gfile-unix.lo libeglib_la-gmisc-unix.lo \ libeglib_la-gmodule-unix.lo libeglib_la-gtimer-unix.lo @@ -116,7 +116,6 @@ am__objects_2 = libeglib_la-gdate-win32.lo libeglib_la-gdir-win32.lo \ libeglib_la-gmodule-win32.lo libeglib_la-gtimer-win32.lo @HOST_WIN32_FALSE@am__objects_3 = $(am__objects_1) @HOST_WIN32_TRUE@am__objects_3 = $(am__objects_2) -@NEED_VASPRINTF_TRUE@am__objects_4 = libeglib_la-vasprintf.lo am_libeglib_la_OBJECTS = libeglib_la-garray.lo \ libeglib_la-gbytearray.lo libeglib_la-gerror.lo \ libeglib_la-ghashtable.lo libeglib_la-giconv.lo \ @@ -128,8 +127,7 @@ am_libeglib_la_OBJECTS = libeglib_la-garray.lo \ libeglib_la-gshell.lo libeglib_la-gspawn.lo \ libeglib_la-gfile.lo libeglib_la-gfile-posix.lo \ libeglib_la-gpattern.lo libeglib_la-gmarkup.lo \ - libeglib_la-gutf8.lo libeglib_la-gunicode.lo $(am__objects_3) \ - $(am__objects_4) + libeglib_la-gutf8.lo libeglib_la-gunicode.lo $(am__objects_3) libeglib_la_OBJECTS = $(am_libeglib_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -353,11 +351,6 @@ unix_files = \ gdate-unix.c gdir-unix.c gfile-unix.c gmisc-unix.c \ gmodule-unix.c gtimer-unix.c - -# some unices and windows do not have an implementation of vasprintf -# used by eglib, use provided implementation instead -@NEED_VASPRINTF_TRUE@vasprintf_files = vasprintf.c -@NEED_VASPRINTF_FALSE@vaprinttf_files = foo.c @HOST_WIN32_FALSE@os_files = $(unix_files) @HOST_WIN32_TRUE@os_files = $(win_files) libeglib_la_SOURCES = \ @@ -367,7 +360,6 @@ libeglib_la_SOURCES = \ garray.c \ gbytearray.c \ gerror.c \ - vasprintf.h \ ghashtable.c \ giconv.c \ gmem.c \ @@ -390,8 +382,7 @@ libeglib_la_SOURCES = \ gutf8.c \ gunicode.c \ unicode-data.h \ - $(os_files) \ - $(vasprintf_files) + $(os_files) libeglib_la_CFLAGS = -g -Wall -D_FORTIFY_SOURCE=2 AM_CPPFLAGS = -I$(srcdir) @@ -491,7 +482,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-gtimer-win32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-gunicode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-gutf8.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-vasprintf.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -759,13 +749,6 @@ libeglib_la-gtimer-win32.lo: gtimer-win32.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeglib_la_CFLAGS) $(CFLAGS) -c -o libeglib_la-gtimer-win32.lo `test -f 'gtimer-win32.c' || echo '$(srcdir)/'`gtimer-win32.c -libeglib_la-vasprintf.lo: vasprintf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeglib_la_CFLAGS) $(CFLAGS) -MT libeglib_la-vasprintf.lo -MD -MP -MF $(DEPDIR)/libeglib_la-vasprintf.Tpo -c -o libeglib_la-vasprintf.lo `test -f 'vasprintf.c' || echo '$(srcdir)/'`vasprintf.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeglib_la-vasprintf.Tpo $(DEPDIR)/libeglib_la-vasprintf.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vasprintf.c' object='libeglib_la-vasprintf.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeglib_la_CFLAGS) $(CFLAGS) -c -o libeglib_la-vasprintf.lo `test -f 'vasprintf.c' || echo '$(srcdir)/'`vasprintf.c - mostlyclean-libtool: -rm -f *.lo diff --git a/eglib/src/gerror.c b/eglib/src/gerror.c index 2ec089c995..43fef97cc4 100644 --- a/eglib/src/gerror.c +++ b/eglib/src/gerror.c @@ -28,10 +28,8 @@ #include #include #include +#include #include - -#include "vasprintf.h" - GError * g_error_new (gpointer domain, gint code, const char *format, ...) { @@ -42,7 +40,7 @@ g_error_new (gpointer domain, gint code, const char *format, ...) err->code = code; va_start (args, format); - if (vasprintf (&err->message, format, args) == -1) + if (g_vasprintf (&err->message, format, args) == -1) err->message = g_strdup_printf ("internal: invalid format string %s", format); va_end (args); @@ -57,7 +55,7 @@ g_error_vnew (gpointer domain, gint code, const char *format, va_list ap) err->domain = domain; err->code = code; - if (vasprintf (&err->message, format, ap) == -1) + if (g_vasprintf (&err->message, format, ap) == -1) err->message = g_strdup_printf ("internal: invalid format string %s", format); return err; @@ -77,7 +75,7 @@ g_error_free (GError *error) { g_return_if_fail (error != NULL); - free (error->message); + g_free (error->message); g_free (error); } diff --git a/eglib/src/gfile-win32.c b/eglib/src/gfile-win32.c index 2dde793dfe..61e23cbe44 100644 --- a/eglib/src/gfile-win32.c +++ b/eglib/src/gfile-win32.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef G_OS_WIN32 #include @@ -68,6 +69,26 @@ int mkstemp (char *tmp_template) return fd; } +gchar * +g_mkdtemp (char *tmp_template) +{ + gunichar2* utf16_template; + + utf16_template = u8to16 (tmp_template); + + utf16_template = _wmktemp(utf16_template); + if (utf16_template && *utf16_template) { + if (_wmkdir (utf16_template) == 0){ + char *ret = u16to8 (utf16_template); + g_free (utf16_template); + return ret; + } + } + + g_free (utf16_template); + return NULL; +} + #ifdef _MSC_VER #pragma warning(disable:4701) #endif diff --git a/eglib/src/giconv.c b/eglib/src/giconv.c index a6f222dfe8..c7723fef5b 100644 --- a/eglib/src/giconv.c +++ b/eglib/src/giconv.c @@ -199,8 +199,11 @@ g_iconv (GIConv cd, gchar **inbytes, gsize *inbytesleft, } else { outleftptr = NULL; } - +#if defined(__NetBSD__) + return iconv (cd->cd, (const gchar **)inbytes, inleftptr, outbytes, outleftptr); +#else return iconv (cd->cd, inbytes, inleftptr, outbytes, outleftptr); +#endif } #endif diff --git a/eglib/src/glib.h b/eglib/src/glib.h index 84ab1ee3f8..d7173264c1 100644 --- a/eglib/src/glib.h +++ b/eglib/src/glib.h @@ -1,6 +1,5 @@ #ifndef __GLIB_H #define __GLIB_H - #include #include #include @@ -9,6 +8,7 @@ #include #include + #ifdef _MSC_VER #pragma include_alias(, ) #endif @@ -126,6 +126,7 @@ void g_free (void *ptr); gpointer g_realloc (gpointer obj, gsize size); gpointer g_malloc (gsize x); gpointer g_malloc0 (gsize x); +gpointer g_calloc (gsize n, gsize x); gpointer g_try_malloc (gsize x); gpointer g_try_realloc (gpointer obj, gsize size); @@ -138,7 +139,7 @@ gpointer g_try_realloc (gpointer obj, gsize size); #define g_alloca(size) alloca (size) gpointer g_memdup (gconstpointer mem, guint byte_size); -static inline gchar *g_strdup (const gchar *str) { if (str) {return strdup (str);} return NULL; } +static inline gchar *g_strdup (const gchar *str) { if (str) { return (gchar*) g_memdup (str, (guint)strlen (str) + 1); } return NULL; } gchar **g_strdupv (gchar **str_array); typedef struct { @@ -146,11 +147,9 @@ typedef struct { gpointer (*realloc) (gpointer mem, gsize n_bytes); void (*free) (gpointer mem); gpointer (*calloc) (gsize n_blocks, gsize n_block_bytes); - gpointer (*try_malloc) (gsize n_bytes); - gpointer (*try_realloc) (gpointer mem, gsize n_bytes); } GMemVTable; -#define g_mem_set_vtable(x) +void g_mem_set_vtable (GMemVTable* vtable); struct _GMemChunk { guint alloc_size; @@ -223,11 +222,11 @@ gint g_printf (gchar const *format, ...); gint g_fprintf (FILE *file, gchar const *format, ...); gint g_sprintf (gchar *string, gchar const *format, ...); gint g_snprintf (gchar *string, gulong n, gchar const *format, ...); +gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap); #define g_vprintf vprintf #define g_vfprintf vfprintf #define g_vsprintf vsprintf #define g_vsnprintf vsnprintf -#define g_vasprintf vasprintf gsize g_strlcpy (gchar *dest, const gchar *src, gsize dest_size); gchar *g_stpcpy (gchar *dest, const char *src); @@ -888,6 +887,12 @@ gboolean g_file_test (const gchar *filename, GFileTest test); #define g_ascii_strtod strtod #define g_ascii_isalnum isalnum +#ifdef WIN32 +gchar *g_mkdtemp (gchar *tmpl); +#else +#define g_mkdtemp mkdtemp +#endif + /* * Pattern matching */ diff --git a/eglib/src/gmarkup.c b/eglib/src/gmarkup.c index 6a0b246a95..4e6c6641fe 100644 --- a/eglib/src/gmarkup.c +++ b/eglib/src/gmarkup.c @@ -367,7 +367,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, if (context->parser.end_element != NULL && context->state == START_ELEMENT){ context->parser.end_element (context, ename, context->user_data, error); if (error != NULL && *error != NULL){ - free (ename); + g_free (ename); goto fail; } } diff --git a/eglib/src/gmem.c b/eglib/src/gmem.c index 565239d1cb..eff478dcbf 100644 --- a/eglib/src/gmem.c +++ b/eglib/src/gmem.c @@ -25,15 +25,45 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include +#if defined (ENABLE_OVERRIDABLE_ALLOCATORS) + +static GMemVTable sGMemVTable = { malloc, realloc, free, calloc }; + +void +g_mem_set_vtable (GMemVTable* vtable) +{ + sGMemVTable.calloc = vtable->calloc ? vtable->calloc : calloc; + sGMemVTable.realloc = vtable->realloc ? vtable->realloc : realloc; + sGMemVTable.malloc = vtable->malloc ? vtable->malloc : malloc; + sGMemVTable.free = vtable->free ? vtable->free : free; +} + +#define G_FREE_INTERNAL sGMemVTable.free +#define G_REALLOC_INTERNAL sGMemVTable.realloc +#define G_CALLOC_INTERNAL sGMemVTable.calloc +#define G_MALLOC_INTERNAL sGMemVTable.malloc +#else + +void +g_mem_set_vtable (GMemVTable* vtable) +{ +} + +#define G_FREE_INTERNAL free +#define G_REALLOC_INTERNAL realloc +#define G_CALLOC_INTERNAL calloc +#define G_MALLOC_INTERNAL malloc +#endif void g_free (void *ptr) { if (ptr != NULL) - free (ptr); + G_FREE_INTERNAL (ptr); } gpointer @@ -58,7 +88,7 @@ gpointer g_realloc (gpointer obj, gsize size) g_free (obj); return 0; } - ptr = realloc (obj, size); + ptr = G_REALLOC_INTERNAL (obj, size); if (ptr) return ptr; g_error ("Could not allocate %i bytes", size); @@ -70,27 +100,31 @@ g_malloc (gsize x) gpointer ptr; if (!x) return 0; - ptr = malloc (x); + ptr = G_MALLOC_INTERNAL (x); if (ptr) return ptr; g_error ("Could not allocate %i bytes", x); } +gpointer g_calloc (gsize n, gsize x) +{ + gpointer ptr; + if (!x || !n) + return 0; + ptr = G_CALLOC_INTERNAL (n, x); + if (ptr) + return ptr; + g_error ("Could not allocate %i (%i * %i) bytes", x*n, n, x); +} gpointer g_malloc0 (gsize x) { - gpointer ptr; - if (!x) - return 0; - ptr = calloc(1,x); - if (ptr) - return ptr; - g_error ("Could not allocate %i bytes", x); + return g_calloc (1,x); } gpointer g_try_malloc (gsize x) { if (x) - return malloc (x); + return G_MALLOC_INTERNAL (x); return 0; } @@ -98,8 +132,8 @@ gpointer g_try_malloc (gsize x) gpointer g_try_realloc (gpointer obj, gsize size) { if (!size) { - g_free (obj); + G_FREE_INTERNAL (obj); return 0; } - return realloc (obj, size); + return G_REALLOC_INTERNAL (obj, size); } diff --git a/eglib/src/gmisc-win32.c b/eglib/src/gmisc-win32.c index f89f37c220..5baec653c3 100644 --- a/eglib/src/gmisc-win32.c +++ b/eglib/src/gmisc-win32.c @@ -30,6 +30,9 @@ #include #include +#ifdef _MSC_VER +#include +#endif #include #include @@ -89,10 +92,10 @@ g_win32_getlocale(void) { LCID lcid = GetThreadLocale(); gchar buf[19]; - gint ccBuf = GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME, buf, 9); + gint ccBuf = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buf, 9); buf[ccBuf - 1] = '-'; - ccBuf += GetLocaleInfo(lcid, LOCALE_SISO3166CTRYNAME, buf + ccBuf, 9); - return strdup(buf); + ccBuf += GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buf + ccBuf, 9); + return g_strdup (buf); } gboolean @@ -116,16 +119,33 @@ g_path_is_absolute (const char *filename) const gchar * g_get_home_dir (void) { - /* FIXME */ - const gchar *drive = g_getenv ("HOMEDRIVE"); - const gchar *path = g_getenv ("HOMEPATH"); gchar *home_dir = NULL; - - if (drive && path) { - home_dir = g_malloc(strlen(drive) + strlen(path) +1); - if (home_dir) { - sprintf(home_dir, "%s%s", drive, path); + +#ifdef _MSC_VER + PWSTR profile_path = NULL; + HRESULT hr = SHGetKnownFolderPath (&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &profile_path); + if (SUCCEEDED(hr)) { + home_dir = u16to8 (profile_path); + CoTaskMemFree (profile_path); + } +#endif + + if (!home_dir) { + home_dir = (gchar *) g_getenv ("USERPROFILE"); + } + + if (!home_dir) { + const gchar *drive = g_getenv ("HOMEDRIVE"); + const gchar *path = g_getenv ("HOMEPATH"); + + if (drive && path) { + home_dir = g_malloc (strlen (drive) + strlen (path) + 1); + if (home_dir) { + sprintf (home_dir, "%s%s", drive, path); + } } + g_free (drive); + g_free (path); } return home_dir; diff --git a/eglib/src/goutput.c b/eglib/src/goutput.c index 779ca96fd2..ef80cff034 100644 --- a/eglib/src/goutput.c +++ b/eglib/src/goutput.c @@ -31,8 +31,6 @@ #include #include -#include "vasprintf.h" - /* The current fatal levels, error is always fatal */ static GLogLevelFlags fatal = G_LOG_LEVEL_ERROR; static GLogFunc default_log_func; @@ -49,7 +47,7 @@ g_print (const gchar *format, ...) va_list args; va_start (args, format); - if (vasprintf (&msg, format, args) < 0) + if (g_vasprintf (&msg, format, args) < 0) return; va_end (args); @@ -57,7 +55,7 @@ g_print (const gchar *format, ...) stdout_handler = default_stdout_handler; stdout_handler (msg); - free (msg); + g_free (msg); } void @@ -67,7 +65,7 @@ g_printerr (const gchar *format, ...) va_list args; va_start (args, format); - if (vasprintf (&msg, format, args) < 0) + if (g_vasprintf (&msg, format, args) < 0) return; va_end (args); @@ -75,7 +73,7 @@ g_printerr (const gchar *format, ...) stderr_handler = default_stderr_handler; stderr_handler (msg); - free (msg); + g_free (msg); } GLogLevelFlags @@ -107,11 +105,11 @@ g_logv (const gchar *log_domain, GLogLevelFlags log_level, const gchar *format, if (!default_log_func) default_log_func = g_log_default_handler; - if (vasprintf (&msg, format, args) < 0) + if (g_vasprintf (&msg, format, args) < 0) return; default_log_func (log_domain, log_level, msg, default_log_func_user_data); - free (msg); + g_free (msg); } void diff --git a/eglib/src/gstr.c b/eglib/src/gstr.c index 3e976c5a2e..8b64da572f 100644 --- a/eglib/src/gstr.c +++ b/eglib/src/gstr.c @@ -32,13 +32,17 @@ #include #include -#include "vasprintf.h" +/* + * g_strndup and g_vasprintf need to allocate memory with g_malloc if + * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free + * rather than free. + */ /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */ gchar * g_strndup (const gchar *str, gsize n) { -#ifdef HAVE_STRNDUP +#if defined (HAVE_STRNDUP) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS) return strndup (str, n); #else if (str) { @@ -52,6 +56,37 @@ g_strndup (const gchar *str, gsize n) #endif } +gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap) +{ +#if defined (HAVE_VASPRINTF) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS) + return vasprintf (ret, fmt, ap); +#else + char *buf; + int len; + size_t buflen; + va_list ap2; + +#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) + ap2 = ap; + len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( ) +#else + va_copy(ap2, ap); + len = vsnprintf(NULL, 0, fmt, ap2); +#endif + + if (len >= 0 && (buf = g_malloc ((buflen = (size_t) (len + 1)))) != NULL) { + len = vsnprintf(buf, buflen, fmt, ap); + *ret = buf; + } else { + *ret = NULL; + len = -1; + } + + va_end(ap2); + return len; +#endif +} + void g_strfreev (gchar **str_array) { @@ -133,7 +168,7 @@ g_strdup_vprintf (const gchar *format, va_list args) int n; char *ret; - n = vasprintf (&ret, format, args); + n = g_vasprintf (&ret, format, args); if (n == -1) return NULL; @@ -148,7 +183,7 @@ g_strdup_printf (const gchar *format, ...) int n; va_start (args, format); - n = vasprintf (&ret, format, args); + n = g_vasprintf (&ret, format, args); va_end (args); if (n == -1) return NULL; diff --git a/eglib/src/vasprintf.c b/eglib/src/vasprintf.c deleted file mode 100644 index 3c21ca4dc0..0000000000 --- a/eglib/src/vasprintf.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include - -int vasprintf(char **ret, const char *fmt, va_list ap) -{ - char *buf; - int len; - size_t buflen; - va_list ap2; - -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - ap2 = ap; - len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( ) -#else - va_copy(ap2, ap); - len = vsnprintf(NULL, 0, fmt, ap2); -#endif - - if (len >= 0 && (buf = malloc ((buflen = (size_t) (len + 1)))) != NULL) { - len = vsnprintf(buf, buflen, fmt, ap); - *ret = buf; - } else { - *ret = NULL; - len = -1; - } - - va_end(ap2); - return len; -} - diff --git a/eglib/src/vasprintf.h b/eglib/src/vasprintf.h deleted file mode 100644 index 3d294541a5..0000000000 --- a/eglib/src/vasprintf.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __VASPRINTF_H -#define __VASPRINTF_H - -#include -#include - -#ifndef HAVE_VASPRINTF -int vasprintf(char **ret, const char *fmt, va_list ap); -#endif - -#endif /* __VASPRINTF_H */ diff --git a/eglib/test/test.c b/eglib/test/test.c index 6dd7bf4746..7c870e9c76 100644 --- a/eglib/test/test.c +++ b/eglib/test/test.c @@ -46,13 +46,6 @@ #include "test.h" extern gint global_passed, global_tests; - -#ifndef HAVE_VASPRINTF - /* systen does not provide a vasprintf function, use the one - provided within eglib itself */ -extern int vasprintf(char **ret, const char *format, va_list ap); -#endif - static gchar *last_result = NULL; gboolean @@ -183,7 +176,7 @@ FAILED(const gchar *format, ...) return NULL; #else va_start(args, format); - n = vasprintf(&ret, format, args); + n = g_vasprintf(&ret, format, args); va_end(args); if(n == -1) { diff --git a/external/boringssl/.clang-format b/external/boringssl/.clang-format new file mode 100644 index 0000000000..5865a7068d --- /dev/null +++ b/external/boringssl/.clang-format @@ -0,0 +1,7 @@ +BasedOnStyle: Google +MaxEmptyLinesToKeep: 3 +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +DerivePointerAlignment: false +PointerAlignment: Right + diff --git a/external/boringssl/.github/PULL_REQUEST_TEMPLATE b/external/boringssl/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000000..6c101eabca --- /dev/null +++ b/external/boringssl/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,7 @@ +Please do not send pull requests to the BoringSSL repository. + +We do, however, take contributions gladly. + +See https://boringssl.googlesource.com/boringssl/+/master/CONTRIBUTING.md + +Thanks! diff --git a/external/boringssl/.gitignore b/external/boringssl/.gitignore new file mode 100644 index 0000000000..a2e3ed2a15 --- /dev/null +++ b/external/boringssl/.gitignore @@ -0,0 +1,6 @@ +build/ +ssl/test/runner/runner +*.swp +*.swo +doc/*.html +doc/doc.css diff --git a/external/boringssl/BUILDING.md b/external/boringssl/BUILDING.md new file mode 100644 index 0000000000..5631ded848 --- /dev/null +++ b/external/boringssl/BUILDING.md @@ -0,0 +1,145 @@ +# Building BoringSSL + +## Build Prerequisites + + * [CMake](https://cmake.org/download/) 2.8.8 or later is required. + + * Perl 5.6.1 or later is required. On Windows, + [Active State Perl](http://www.activestate.com/activeperl/) has been + reported to work, as has MSYS Perl. + [Strawberry Perl](http://strawberryperl.com/) also works but it adds GCC + to `PATH`, which can confuse some build tools when identifying the compiler + (removing `C:\Strawberry\c\bin` from `PATH` should resolve any problems). + If Perl is not found by CMake, it may be configured explicitly by setting + `PERL_EXECUTABLE`. + + * On Windows you currently must use [Ninja](https://ninja-build.org/) + 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](https://www.python.org/downloads/) is required (Python 2.7.5 works). + + * On Windows only, [Yasm](http://yasm.tortall.net/) is required. If not found + by CMake, it may be configured explicitly by setting + `CMAKE_ASM_NASM_COMPILER`. + + * A C compiler is required. On Windows, MSVC 14 (Visual Studio 2015) or later + with Platform SDK 8.1 or later are supported. Recent versions of GCC (4.8+) + and Clang should work on non-Windows platforms, and maybe on Windows too. + To build the tests, you also need a C++ compiler with C++11 support. + + * [Go](https://golang.org/dl/) is required. If not found by CMake, the go + executable may be configured explicitly by setting `GO_EXECUTABLE`. + + * To build the x86 and x86\_64 assembly, your assembler must support AVX2 + instructions. If using GNU binutils, you must have 2.22 or later. + +## Building + +Using Ninja (note the 'N' is capitalized in the cmake invocation): + + mkdir build + cd build + cmake -GNinja .. + ninja + +Using Make (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. Pass `-DCMAKE_BUILD_TYPE=Release` to +`cmake` to configure a release build. + +If you want to cross-compile then there is an example toolchain file for 32-bit +Intel in `util/`. Wipe out the build directory, recreate it and run `cmake` like +this: + + cmake -DCMAKE_TOOLCHAIN_FILE=../util/32-bit-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 `#include`s +the BoringSSL headers. + +In order to serve environments where code-size is important as well as those +where performance is the overriding concern, `OPENSSL_SMALL` can be defined to +remove some code that is especially large. + +See [CMake's documentation](https://cmake.org/cmake/help/v3.4/manual/cmake-variables.7.html) +for other variables which may be used to configure the build. + +### Building for Android + +It's possible to build BoringSSL with the Android NDK using CMake. This has +been tested with version 10d of the NDK. + +Unpack the Android NDK somewhere and export `ANDROID_NDK` to point to the +directory. Then make a build directory as above and run CMake like this: + + cmake -DANDROID_ABI=armeabi-v7a \ + -DCMAKE_TOOLCHAIN_FILE=../third_party/android-cmake/android.toolchain.cmake \ + -DANDROID_NATIVE_API_LEVEL=16 \ + -GNinja .. + +Once you've run that, Ninja should produce Android-compatible binaries. You +can replace `armeabi-v7a` in the above with `arm64-v8a` and use API level 21 or +higher to build aarch64 binaries. + +For other options, see [android-cmake's documentation](./third_party/android-cmake/README.md). + +## 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. + +## Embedded ARM + +ARM, unlike Intel, does not have an instruction that allows applications to +discover the capabilities of the processor. Instead, the capability information +has to be provided by the operating system somehow. + +BoringSSL will try to use `getauxval` to discover the capabilities and, failing +that, will probe for NEON support by executing a NEON instruction and handling +any illegal-instruction signal. But some environments don't support that sort +of thing and, for them, it's possible to configure the CPU capabilities +at compile time. + +If you define `OPENSSL_STATIC_ARMCAP` then you can define any of the following +to enabling the corresponding ARM feature. + + * `OPENSSL_STATIC_ARMCAP_NEON` or `__ARM_NEON__` (note that the latter is set by compilers when NEON support is enabled). + * `OPENSSL_STATIC_ARMCAP_AES` + * `OPENSSL_STATIC_ARMCAP_SHA1` + * `OPENSSL_STATIC_ARMCAP_SHA256` + * `OPENSSL_STATIC_ARMCAP_PMULL` + +Note that if a feature is enabled in this way, but not actually supported at +run-time, BoringSSL will likely crash. + +# Running tests + +There are two sets of tests: the C/C++ tests and the blackbox tests. For former +are built by Ninja and can be run from the top-level directory with `go run +util/all_tests.go`. The latter have to be run separately by running `go test` +from within `ssl/test/runner`. + +Both sets of tests may also be run with `ninja -C build run_tests`, but CMake +3.2 or later is required to avoid Ninja's output buffering. diff --git a/external/boringssl/CMakeLists.txt b/external/boringssl/CMakeLists.txt new file mode 100644 index 0000000000..4e63c89fbb --- /dev/null +++ b/external/boringssl/CMakeLists.txt @@ -0,0 +1,232 @@ +cmake_minimum_required (VERSION 2.8.10) + +# Defer enabling C and CXX languages. +project (BoringSSL NONE) + +if(WIN32) + # On Windows, prefer cl over gcc if both are available. By default most of + # the CMake generators prefer gcc, even on Windows. + set(CMAKE_GENERATOR_CC cl) +endif() + +enable_language(C) +enable_language(CXX) + +if(ANDROID) + # Android-NDK CMake files reconfigure the path and so Go and Perl won't be + # found. However, ninja will still find them in $PATH if we just name them. + set(PERL_EXECUTABLE "perl") + # set(GO_EXECUTABLE "go") +else() + find_package(Perl REQUIRED) + # find_program(GO_EXECUTABLE go) +endif() + +#if (NOT GO_EXECUTABLE) +# message(FATAL_ERROR "Could not find Go") +#endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(C_CXX_FLAGS "-Wall -Wformat=2 -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS}") + if(ANDROID) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${C_CXX_FLAGS}") + elseif(CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ ${C_CXX_FLAGS}") + endif() +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 + "C4267" # conversion from 'size_t' to 'int', possible loss of data + "C4371" # layout of class may have changed from a previous version of the + # compiler due to better packing of member '...' + "C4388" # 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 + "C4464" # relative include path contains '..' + "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. + "C4623" # default constructor was implicitly defined as deleted + "C4625" # copy constructor could not be generated because a base class + # copy constructor is inaccessible or deleted + "C4626" # assignment operator could not be generated because a base class + # assignment operator is inaccessible or deleted + "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' + "C5027" # move assignment operator was implicitly defined as deleted + ) + set(MSVC_LEVEL4_WARNINGS_LIST + # See https://connect.microsoft.com/VisualStudio/feedback/details/1217660/warning-c4265-when-using-functional-header + "C4265" # class has virtual functions, but destructor is not virtual + ) + string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR + ${MSVC_DISABLED_WARNINGS_LIST}) + string(REPLACE "C" " -w4" MSVC_LEVEL4_WARNINGS_STR + ${MSVC_LEVEL4_WARNINGS_LIST}) + set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}") + set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}") + add_definitions(-D_HAS_EXCEPTIONS=0) + add_definitions(-DWIN32_LEAN_AND_MEAN) + add_definitions(-DNOMINMAX) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Allow use of fopen +endif() + +if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.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() + +if(CMAKE_COMPILER_IS_GNUCXX) + if ((CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR + CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") + endif() +endif() + +# pthread_rwlock_t requires a feature flag. +if(NOT WIN32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=700") +endif() + +if(FUZZ) + if(!CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message("You need to build with Clang for fuzzing to work") + endif() + + add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE) + set(RUNNER_ARGS "-fuzzer") + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + link_directories(.) +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 "armv5te") + set(ARCH "arm") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv6") + set(ARCH "arm") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7-a") + set(ARCH "arm") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") + set(ARCH "aarch64") +else() + message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +if (ANDROID AND ${ARCH} STREQUAL "arm") + # The Android-NDK CMake files somehow fail to set the -march flag for + # assembly files. Without this flag, the compiler believes that it's + # building for ARMv5. + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -march=${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() + +if (OPENSSL_NO_ASM) + add_definitions(-DOPENSSL_NO_ASM) + set(ARCH "generic") +endif() + +# Declare a dummy target to build all unit tests. Test targets should inject +# themselves as dependencies next to the target definition. +if(ENABLE_TESTS) +add_custom_target(all_tests) +endif() + +add_subdirectory(crypto) +add_subdirectory(ssl) +if(ENABLE_TESTS) +add_subdirectory(ssl/test) +endif() +add_subdirectory(tool) +if(ENABLE_DECREPIT) +add_subdirectory(decrepit) +endif() + +if(FUZZ) + add_subdirectory(fuzz) +endif() + +if (NOT ${CMAKE_VERSION} VERSION_LESS "3.2") + # USES_TERMINAL is only available in CMake 3.2 or later. + set(MAYBE_USES_TERMINAL USES_TERMINAL) +endif() + +set ( + BORINGSSL_OBJECTS + $ + ${crypto_objects_dependencies} + $ + ${ssl_objects_dependencies} + PARENT_SCOPE +) + +# add_custom_target( +# run_tests +# COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir +# ${CMAKE_BINARY_DIR} +# COMMAND cd ssl/test/runner +# COMMAND ${GO_EXECUTABLE} test -shim-path $ +# WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +# DEPENDS all_tests bssl_shim +# ${MAYBE_USES_TERMINAL}) diff --git a/external/boringssl/CONTRIBUTING.md b/external/boringssl/CONTRIBUTING.md new file mode 100644 index 0000000000..8907cc98cb --- /dev/null +++ b/external/boringssl/CONTRIBUTING.md @@ -0,0 +1,49 @@ +Want to contribute? Great! First, read this page (including the small print at the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. +Before you start working on a larger contribution, you should get in touch with +us first via email with your idea so that we can help out and possibly guide +you. Coordinating up front makes it much easier to avoid frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. We +use [Gerrit](https://boringssl-review.googlesource.com) for this purpose. + +#### Setup +If you have not done so on this machine, you will need to set up a password for +Gerrit. Sign in with a Google account, visit +[this link](https://boringssl.googlesource.com/), and click the "Generate +Password" link in the top right. You will also need to prepare your checkout to +[add Change-Ids](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html) +on commit. Run: + + curl -Lo .git/hooks/commit-msg https://boringssl-review.googlesource.com/tools/hooks/commit-msg + chmod u+x .git/hooks/commit-msg + +#### Uploading changes +To upload a change, push it to the special `refs/for/master` target: + + git push origin HEAD:refs/for/master + +The output will then give you a link to the change. Add `agl@google.com` and +`davidben@google.com` as reviewers. + +Pushing a commit with the same Change-Id as an existing change will upload a new +version of it. (Use the `git rebase` or `git commit --amend` commands.) + +For more detailed instructions, see the +[Gerrit User Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html). + +### The small print +Contributions made by corporations are covered by a different agreement than +the one above, the +[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate). diff --git a/external/boringssl/FUZZING.md b/external/boringssl/FUZZING.md new file mode 100644 index 0000000000..9f4edef195 --- /dev/null +++ b/external/boringssl/FUZZING.md @@ -0,0 +1,63 @@ +# Fuzz testing + +Modern fuzz testers are very effective and we wish to use them to ensure that no silly bugs creep into BoringSSL. + +We primarily use Clang's [libFuzzer](http://llvm.org/docs/LibFuzzer.html) for fuzz testing and there are a number of fuzz testing functions in `fuzz/`. They are not built by default because they require libFuzzer at build time. + +In order to build the fuzz tests you will need at least Clang 3.7. Pass `-DFUZZ=1` on the CMake command line to enable building BoringSSL with coverage and AddressSanitizer, and to build the fuzz test binaries. You'll probably need to set the `CC` and `CXX` environment variables too, like this: + +``` +CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 .. +``` + +In order for the fuzz tests to link, the linker needs to find libFuzzer. This is not commonly provided and you may need to download the [Clang source code](http://llvm.org/releases/download.html) and do the following: + +``` +svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer +clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer +ar ruv libFuzzer.a Fuzzer*.o +``` + +Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory. + +From the `build/` directory, you can then run the fuzzers. For example: + +``` +./fuzz/cert -max_len=3072 -jobs=32 -workers=32 ../fuzz/cert_corpus/ +``` + +The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing. By default, libFuzzer uses the largest test in the corpus (or 64 if empty) as the maximum test case length. The `max_len` argument overrides this. + +The recommended values of `max_len` for each test are: + +| Test | `max_len` value | +|------------|-----------------| +| `cert` | 3072 | +| `client` | 20000 | +| `pkcs8` | 2048 | +| `privkey` | 2048 | +| `server` | 4096 | +| `spki` | 1024 | +| `read_pem` | 512 | + +These were determined by rounding up the length of the largest case in the corpus. + +There are directories in `fuzz/` for each of the fuzzing tests which contain seed files for fuzzing. Some of the seed files were generated manually but many of them are “interesting†results generated by the fuzzing itself. (Where “interesting†means that it triggered a previously unknown path in the code.) + +## Minimising the corpuses + +When a large number of new seeds are available, it's a good idea to minimise the corpus so that different seeds that trigger the same code paths can be deduplicated. + +In order to minimise all the corpuses, build for fuzzing and run `./fuzz/minimise_corpuses.sh`. Note that minimisation is, oddly, often not idempotent for unknown reasons. + +## Fuzzer mode + +When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` defined. This modifies the library, particularly the TLS stack, to be more friendly to fuzzers. It will: + +* Replace `RAND_bytes` with a deterministic PRNG. Call `RAND_reset_for_fuzzing()` at the start of fuzzers which use `RAND_bytes` to reset the PRNG state. + +* Modify the TLS stack to perform all signature checks (CertificateVerify and ServerKeyExchange) and the Finished check, but always act as if the check succeeded. + +* Treat every cipher as the NULL cipher. + +This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol. diff --git a/external/boringssl/INCORPORATING.md b/external/boringssl/INCORPORATING.md new file mode 100644 index 0000000000..d53f2b5298 --- /dev/null +++ b/external/boringssl/INCORPORATING.md @@ -0,0 +1,90 @@ +# Incorporating BoringSSL into a project + +**Note**: if your target project is not a Google project then first read the +[main README](/README.md) about the purpose of BoringSSL. + +## Directory layout + +Typically projects create a `third_party/boringssl` directory to put +BoringSSL-specific files into. The source code of BoringSSL itself goes into +`third_party/boringssl/src`, either by copying or as a +[submodule](https://git-scm.com/docs/git-submodule). + +It's generally a mistake to put BoringSSL's source code into +`third_party/boringssl` directly because pre-built files and custom build files +need to go somewhere and merging these with the BoringSSL source code makes +updating things more complex. + +## Build support + +BoringSSL is designed to work with many different build systems. Currently, +different projects use [GYP](https://gyp.gsrc.io/), +[GN](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/quick_start.md), +[Bazel](http://bazel.io/) and [Make](https://www.gnu.org/software/make/) to +build BoringSSL, without too much pain. + +The development build system is CMake and the CMake build knows how to +automatically generate the intermediate files that BoringSSL needs. However, +outside of the CMake environment, these intermediates are generated once and +checked into the incorporating project's source repository. This avoids +incorporating projects needing to support Perl and Go in their build systems. + +The script [`util/generate_build_files.py`](/util/generate_build_files.py) +expects to be run from the `third_party/boringssl` directory and to find the +BoringSSL source code in `src/`. You should pass it a single argument: the name +of the build system that you're using. If you don't use any of the supported +build systems then you should augment `generate_build_files.py` with support +for it. + +The script will pregenerate the intermediate files (see +[BUILDING.md](/BUILDING.md) for details about which tools will need to be +installed) and output helper files for that build system. It doesn't generate a +complete build script, just file and test lists, which change often. For +example, see the +[file](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated.gni) +and +[test](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated_tests.gni) +lists generated for GN in Chromium. + +Generally one checks in these generated files alongside the hand-written build +files. Periodically an engineer updates the BoringSSL revision, regenerates +these files and checks in the updated result. As an example, see how this is +done [in Chromium](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/). + +## Defines + +BoringSSL does not present a lot of configurability in order to reduce the +number of configurations that need to be tested. But there are a couple of +\#defines that you may wish to set: + +`OPENSSL_NO_ASM` prevents the use of assembly code (although it's up to you to +ensure that the build system doesn't link it in if you wish to reduce binary +size). This will have a significant performance impact but can be useful if you +wish to use tools like +[AddressSanitizer](http://clang.llvm.org/docs/AddressSanitizer.html) that +interact poorly with assembly code. + +`OPENSSL_SMALL` removes some code that is especially large at some performance +cost. + +## Symbols + +You cannot link multiple versions of BoringSSL or OpenSSL into a single binary +without dealing with symbol conflicts. If you are statically linking multiple +versions together, there's not a lot that can be done because C doesn't have a +module system. + +If you are using multiple versions in a single binary, in different shared +objects, ensure you build BoringSSL with `-fvisibility=hidden` and do not +export any of BoringSSL's symbols. This will prevent any collisions with other +verisons that may be included in other shared objects. Note that this requires +that all callers of BoringSSL APIs live in the same shared object as BoringSSL. + +If you require that BoringSSL APIs be used across shared object boundaries, +continue to build with `-fvisibility=hidden` but define +`BORINGSSL_SHARED_LIBRARY` in both BoringSSL and consumers. BoringSSL's own +source files (but *not* consumers' source files) must also build with +`BORINGSSL_IMPLEMENTATION` defined. This will export BoringSSL's public symbols +in the resulting shared object while hiding private symbols. However note that, +as with a static link, this precludes dynamically linking with another version +of BoringSSL or OpenSSL. diff --git a/external/boringssl/LICENSE b/external/boringssl/LICENSE new file mode 100644 index 0000000000..a25996f720 --- /dev/null +++ b/external/boringssl/LICENSE @@ -0,0 +1,192 @@ +BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL +licensing. Files that are completely new have a Google copyright and an ISC +license. This license is reproduced at the bottom of this file. + +Contributors to BoringSSL are required to follow the CLA rules for Chromium: +https://cla.developers.google.com/clas + +Some files from Intel are under yet another license, which is also included +underneath. + +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. + +The following are Google-internal bug numbers where explicit permission from +some authors is recorded for use of their work. (This is purely for our own +record keeping.) + 27287199 + 27287880 + 27287883 + + 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.] + */ + + +ISC license used for completely new code in BoringSSL: + +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + +Some files from Intel carry the following license: + +# 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. diff --git a/external/boringssl/PORTING.md b/external/boringssl/PORTING.md new file mode 100644 index 0000000000..f953e746d5 --- /dev/null +++ b/external/boringssl/PORTING.md @@ -0,0 +1,187 @@ +# Porting from OpenSSL to BoringSSL + +BoringSSL is an OpenSSL derivative and is mostly source-compatible, for the +subset of OpenSSL retained. Libraries ideally need little to no changes for +BoringSSL support, provided they do not use removed APIs. In general, see if the +library compiles and, on failure, consult the documentation in the header files +and see if problematic features can be removed. + +In some cases, BoringSSL-specific code may be necessary. In that case, the +`OPENSSL_IS_BORINGSSL` preprocessor macro may be used in `#ifdef`s. This macro +should also be used in lieu of the presence of any particular function to detect +OpenSSL vs BoringSSL in configure scripts, etc., where those are necessary. + +For convenience, BoringSSL defines upstream's `OPENSSL_NO_*` feature macros +corresponding to removed features. These may also be used to disable code which +uses a removed feature. + +Note: BoringSSL does *not* have a stable API or ABI. It must be updated with its +consumers. It is not suitable for, say, a system library in a traditional Linux +distribution. For instance, Chromium statically links the specific revision of +BoringSSL it was built against. Likewise, Android's system-internal copy of +BoringSSL is not exposed by the NDK and must not be used by third-party +applications. + + +## Major API changes + +### Integer types + +Some APIs have been converted to use `size_t` for consistency and to avoid +integer overflows at the API boundary. (Existing logic uses a mismash of `int`, +`long`, and `unsigned`.) For the most part, implicit casts mean that existing +code continues to compile. In some cases, this may require BoringSSL-specific +code, particularly to avoid compiler warnings. + +Most notably, the `STACK_OF(T)` types have all been converted to use `size_t` +instead of `int` for indices and lengths. + +### Reference counts + +Some external consumers increment reference counts directly by calling +`CRYPTO_add` with the corresponding `CRYPTO_LOCK_*` value. + +These APIs no longer exist in BoringSSL. Instead, code which increments +reference counts should call the corresponding `FOO_up_ref` function, such as +`EVP_PKEY_up_ref`. Note that not all of these APIs are present in OpenSSL and +may require `#ifdef`s. + +### Error codes + +OpenSSL's errors are extremely specific, leaking internals of the library, +including even a function code for the function which emitted the error! As some +logic in BoringSSL has been rewritten, code which conditions on the error may +break (grep for `ERR_GET_REASON` and `ERR_GET_FUNC`). This danger also exists +when upgrading OpenSSL versions. + +Where possible, avoid conditioning on the exact error reason. Otherwise, a +BoringSSL `#ifdef` may be necessary. Exactly how best to resolve this issue is +still being determined. It's possible some new APIs will be added in the future. + +Function codes have been completely removed. Remove code which conditions on +these as it will break with the slightest change in the library, OpenSSL or +BoringSSL. + +### `*_ctrl` functions + +Some OpenSSL APIs are implemented with `ioctl`-style functions such as +`SSL_ctrl` and `EVP_PKEY_CTX_ctrl`, combined with convenience macros, such as + + # define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) + +In BoringSSL, these macros have been replaced with proper functions. The +underlying `_ctrl` functions have been removed. + +For convenience, `SSL_CTRL_*` values are retained as macros to `doesnt_exist` so +existing code which uses them (or the wrapper macros) in `#ifdef` expressions +will continue to function. However, the macros themselves will not work. + +Switch any `*_ctrl` callers to the macro/function versions. This works in both +OpenSSL and BoringSSL. Note that BoringSSL's function versions will be +type-checked and may require more care with types. + +### HMAC `EVP_PKEY`s + +`EVP_PKEY_HMAC` is removed. Use the `HMAC_*` functions in `hmac.h` instead. This +is compatible with OpenSSL. + +### DSA `EVP_PKEY`s + +`EVP_PKEY_DSA` is deprecated. It is currently still possible to parse DER into a +DSA `EVP_PKEY`, but signing or verifying with those objects will not work. + +### DES + +The `DES_cblock` type has been switched from an array to a struct to avoid the +pitfalls around array types in C. Where features which require DES cannot be +disabled, BoringSSL-specific codepaths may be necessary. + +### TLS renegotiation + +OpenSSL enables TLS renegotiation by default and accepts renegotiation requests +from the peer transparently. Renegotiation is an extremely problematic protocol +feature, so BoringSSL rejects peer renegotiations by default. + +To enable renegotiation, call `SSL_set_renegotiate_mode` and set it to +`ssl_renegotiate_once` or `ssl_renegotiate_freely`. Renegotiation is only +supported as a client in SSL3/TLS and the HelloRequest must be received at a +quiet point in the application protocol. This is sufficient to support the +common use of requesting a new client certificate between an HTTP request and +response in (unpipelined) HTTP/1.1. + +Things which do not work: + +* There is no support for renegotiation as a server. + +* There is no support for renegotiation in DTLS. + +* There is no support for initiating renegotiation; `SSL_renegotiate` always + fails and `SSL_set_state` does nothing. + +* Interleaving application data with the new handshake is forbidden. + +* If a HelloRequest is received while `SSL_write` has unsent application data, + the renegotiation is rejected. + +### Lowercase hexadecimal + +BoringSSL's `BN_bn2hex` function uses lowercase hexadecimal digits instead of +uppercase. Some code may require changes to avoid being sensitive to this +difference. + +### Legacy ASN.1 functions + +OpenSSL's ASN.1 stack uses `d2i` functions for parsing. They have the form: + + RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len); + +In addition to returning the result, OpenSSL places it in `*out` if `out` is +not `NULL`. On input, if `*out` is not `NULL`, OpenSSL will usually (but not +always) reuse that object rather than allocating a new one. In BoringSSL, these +functions are compatibility wrappers over a newer ASN.1 stack. Even if `*out` +is not `NULL`, these wrappers will always allocate a new object and free the +previous one. + +Ensure that callers do not rely on this object reuse behavior. It is +recommended to avoid the `out` parameter completely and always pass in `NULL`. +Note that less error-prone APIs are available for BoringSSL-specific code (see +below). + +## Optional BoringSSL-specific simplifications + +BoringSSL makes some changes to OpenSSL which simplify the API but remain +compatible with OpenSSL consumers. In general, consult the BoringSSL +documentation for any functions in new BoringSSL-only code. + +### Return values + +Most OpenSSL APIs return 1 on success and either 0 or -1 on failure. BoringSSL +has narrowed most of these to 1 on success and 0 on failure. BoringSSL-specific +code may take advantage of the less error-prone APIs and use `!` to check for +errors. + +### Initialization + +OpenSSL has a number of different initialization functions for setting up error +strings and loading algorithms, etc. All of these functions still exist in +BoringSSL for convenience, but they do nothing and are not necessary. + +The one exception is `CRYPTO_library_init`. In `BORINGSSL_NO_STATIC_INITIALIZER` +builds, it must be called to query CPU capabitilies before the rest of the +library. In the default configuration, this is done with a static initializer +and is also unnecessary. + +### Threading + +OpenSSL provides a number of APIs to configure threading callbacks and set up +locks. Without initializing these, the library is not thread-safe. Configuring +these does nothing in BoringSSL. Instead, BoringSSL calls pthreads and the +corresponding Windows APIs internally and is always thread-safe where the API +guarantees it. + +### ASN.1 + +BoringSSL is in the process of deprecating OpenSSL's `d2i` and `i2d` in favor of +new functions using the much less error-prone `CBS` and `CBB` types. +BoringSSL-only code should use those functions where available. diff --git a/external/boringssl/README.md b/external/boringssl/README.md new file mode 100644 index 0000000000..4caedb76a8 --- /dev/null +++ b/external/boringssl/README.md @@ -0,0 +1,32 @@ +# BoringSSL + +BoringSSL is a fork of OpenSSL that is designed to meet Google's needs. + +Although BoringSSL is an open source project, it is not intended for general +use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing +so is likely to be frustrating because there are no guarantees of API or ABI +stability. + +Programs ship their own copies of BoringSSL when they use it and we update +everything as needed when deciding to make API changes. This allows us to +mostly avoid compromises in the name of compatibility. It works for us, but it +may not work for you. + +BoringSSL arose because Google used OpenSSL for many years in various ways and, +over time, built up a large number of patches that were maintained while +tracking upstream OpenSSL. As Google's product portfolio became more complex, +more copies of OpenSSL sprung up and the effort involved in maintaining all +these patches in multiple places was growing steadily. + +Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's +not part of the NDK) and a number of other apps/programs. + +There are other files in this directory which might be helpful: + + * [PORTING.md](/PORTING.md): how to port OpenSSL-using code to BoringSSL. + * [BUILDING.md](/BUILDING.md): how to build BoringSSL + * [INCORPORATING.md](/INCORPORATING.md): how to incorporate BoringSSL into a project. + * [STYLE.md](/STYLE.md): rules and guidelines for coding style. + * include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html). + * [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL. + * [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL. diff --git a/external/boringssl/STYLE.md b/external/boringssl/STYLE.md new file mode 100644 index 0000000000..17295b4f6d --- /dev/null +++ b/external/boringssl/STYLE.md @@ -0,0 +1,197 @@ +# BoringSSL Style Guide + +BoringSSL usually follows the +[Google C++ style guide](https://google.github.io/styleguide/cppguide.html), +The rest of this document describes differences and clarifications on +top of the base guide. + + +## Legacy code + +As a derivative of OpenSSL, BoringSSL contains a lot of legacy code that +does not follow this style guide. Particularly where public API is +concerned, balance consistency within a module with the benefits of a +given rule. Module-wide deviations on naming should be respected while +integer and return value conventions take precedence over consistency. + +Modules from OpenSSL's legacy ASN.1 and X.509 stack are retained for +compatibility and left largely unmodified. To ease importing patches from +upstream, they match OpenSSL's new indentation style. For Emacs, +`doc/openssl-c-indent.el` from OpenSSL may be helpful in this. + + +## Language + +The majority of the project is in C, so C++-specific rules in the +Google style guide do not apply. Support for C99 features depends on +our target platforms. Typically, Chromium's target MSVC is the most +restrictive. + +Variable declarations in the middle of a function are allowed. + +Comments should be `/* C-style */` for consistency. + +When declaration pointer types, `*` should be placed next to the variable +name, not the type. So + + uint8_t *ptr; + +not + + uint8_t* ptr; + +Rather than `malloc()` and `free()`, use the wrappers `OPENSSL_malloc()` +and `OPENSSL_free()`. Use the standard C `assert()` function freely. + +For new constants, prefer enums when the values are sequential and typed +constants for flags. If adding values to an existing set of `#define`s, +continue with `#define`. + + +## Formatting + +Single-statement blocks are not allowed. All conditions and loops must +use braces: + + if (foo) { + do_something(); + } + +not + + if (foo) + do_something(); + + +## Integers + +Prefer using explicitly-sized integers where appropriate rather than +generic C ones. For instance, to represent a byte, use `uint8_t`, not +`unsigned char`. Likewise, represent a two-byte field as `uint16_t`, not +`unsigned short`. + +Sizes are represented as `size_t`. + +Within a struct that is retained across the lifetime of an SSL +connection, if bounds of a size are known and it's easy, use a smaller +integer type like `uint8_t`. This is a "free" connection footprint +optimization for servers. Don't make code significantly more complex for +it, and do still check the bounds when passing in and out of the +struct. This narrowing should not propagate to local variables and +function parameters. + +When doing arithmetic, account for overflow conditions. + +Except with platform APIs, do not use `ssize_t`. MSVC lacks it, and +prefer out-of-band error signaling for `size_t` (see Return values). + + +## Naming + +Follow Google naming conventions in C++ files. In C files, use the +following naming conventions for consistency with existing OpenSSL and C +styles: + +Define structs with typedef named `TYPE_NAME`. The corresponding struct +should be named `struct type_name_st`. + +Name public functions as `MODULE_function_name`, unless the module +already uses a different naming scheme for legacy reasons. The module +name should be a type name if the function is a method of a particular +type. + +Some types are allocated within the library while others are initialized +into a struct allocated by the caller, often on the stack. Name these +functions `TYPE_NAME_new`/`TYPE_NAME_free` and +`TYPE_NAME_init`/`TYPE_NAME_cleanup`, respectively. All `TYPE_NAME_free` +functions must do nothing on `NULL` input. + +If a variable is the length of a pointer value, it has the suffix +`_len`. An output parameter is named `out` or has an `out_` prefix. For +instance, For instance: + + uint8_t *out, + size_t *out_len, + const uint8_t *in, + size_t in_len, + +Name public headers like `include/openssl/evp.h` with header guards like +`OPENSSL_HEADER_EVP_H`. Name internal headers like +`crypto/ec/internal.h` with header guards like +`OPENSSL_HEADER_EC_INTERNAL_H`. + +Name enums like `enum unix_hacker_t`. For instance: + + enum should_free_handshake_buffer_t { + free_handshake_buffer, + dont_free_handshake_buffer, + }; + + +## Return values + +As even `malloc` may fail in BoringSSL, the vast majority of functions +will have a failure case. Functions should return `int` with one on +success and zero on error. Do not overload the return value to both +signal success/failure and output an integer. For example: + + OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out); + +If a function needs more than a true/false result code, define an enum +rather than arbitrarily assigning meaning to int values. + +If a function outputs a pointer to an object on success and there are no +other outputs, return the pointer directly and `NULL` on error. + + +## Parameters + +Where not constrained by legacy code, parameter order should be: + +1. context parameters +2. output parameters +3. input parameters + +For example, + + /* 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); + + +## Documentation + +All public symbols must have a documentation comment in their header +file. The style is based on that of Go. The first sentence begins with +the symbol name, optionally prefixed with "A" or "An". Apart from the +initial mention of symbol, references to other symbols or parameter +names should be surrounded by |pipes|. + +Documentation should be concise but completely describe the exposed +behavior of the function. Pay special note to success/failure behaviors +and caller obligations on object lifetimes. If this sacrifices +conciseness, consider simplifying the function's behavior. + + /* 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); + +Explicitly mention any surprising edge cases or deviations from common +return value patterns in legacy functions. + + /* 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); + +Document private functions in their `internal.h` header or, if static, +where defined. diff --git a/external/boringssl/codereview.settings b/external/boringssl/codereview.settings new file mode 100644 index 0000000000..1e123a1912 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/CMakeLists.txt b/external/boringssl/crypto/CMakeLists.txt new file mode 100644 index 0000000000..94e47ea1f5 --- /dev/null +++ b/external/boringssl/crypto/CMakeLists.txt @@ -0,0 +1,277 @@ +include_directories(../include) + +if(APPLE) + if (${ARCH} STREQUAL "x86") + set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2") + 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 "arm") + set(PERLASM_STYLE linux32) + elseif (${ARCH} STREQUAL "x86") + set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2") + set(PERLASM_STYLE elf) + else() + set(PERLASM_STYLE elf) + endif() + set(ASM_EXT S) + enable_language(ASM) + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack") +else() + if (CMAKE_CL_64) + message("Using nasm") + set(PERLASM_STYLE nasm) + else() + message("Using win32n") + set(PERLASM_STYLE win32n) + set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2") + 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_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest} + DEPENDS + ${src} + ${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl + ${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() + +# 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) +add_subdirectory(curve25519) +add_subdirectory(newhope) + +# 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(cmac) +add_subdirectory(evp) +add_subdirectory(hkdf) +add_subdirectory(pem) +add_subdirectory(x509) +add_subdirectory(x509v3) + +# Level 4 +add_subdirectory(pkcs8) + +# Test support code +if(ENABLE_TESTS) +add_subdirectory(test) +endif() + +set( + crypto_objects_dependencies + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + PARENT_SCOPE +) + +add_library( + crypto-objects OBJECT + + cpu-aarch64-linux.c + cpu-arm.c + cpu-arm-linux.c + cpu-intel.c + crypto.c + ex_data.c + mem.c + refcount_c11.c + refcount_lock.c + thread.c + thread_none.c + thread_pthread.c + thread_win.c + time_support.c + + ${CRYPTO_ARCH_SOURCES} +) + + + +add_library( + crypto + + cpu-aarch64-linux.c + cpu-arm.c + cpu-arm-linux.c + cpu-intel.c + crypto.c + ex_data.c + mem.c + refcount_c11.c + refcount_lock.c + thread.c + thread_none.c + thread_pthread.c + thread_win.c + time_support.c + + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ +) + +if(NOT MSVC AND NOT ANDROID) + target_link_libraries(crypto pthread) +endif() + +if(ENABLE_TESTS) +add_executable( + constant_time_test + + constant_time_test.c + + $ +) + +target_link_libraries(constant_time_test crypto) +add_dependencies(all_tests constant_time_test) + +add_executable( + thread_test + + thread_test.c + + $ +) + +target_link_libraries(thread_test crypto) +add_dependencies(all_tests thread_test) + +add_executable( + refcount_test + + refcount_test.c +) + +target_link_libraries(refcount_test crypto) +add_dependencies(all_tests refcount_test) +endif() diff --git a/external/boringssl/crypto/aes/CMakeLists.txt b/external/boringssl/crypto/aes/CMakeLists.txt new file mode 100644 index 0000000000..0470585696 --- /dev/null +++ b/external/boringssl/crypto/aes/CMakeLists.txt @@ -0,0 +1,74 @@ +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) + +if(ENABLE_TESTS) +add_executable( + aes_test + + aes_test.cc + $ +) + +target_link_libraries(aes_test crypto) +add_dependencies(all_tests aes_test) +endif() diff --git a/external/boringssl/crypto/aes/aes.c b/external/boringssl/crypto/aes/aes.c new file mode 100644 index 0000000000..882391986d --- /dev/null +++ b/external/boringssl/crypto/aes/aes.c @@ -0,0 +1,1142 @@ +/* ==================================================================== + * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include + +#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 = ((uint32_t)Td4[(t0 >> 24)] << 24) ^ + ((uint32_t)Td4[(t3 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t2 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t1) & 0xff]) ^ rk[0]; + PUTU32(out, s0); + s1 = ((uint32_t)Td4[(t1 >> 24)] << 24) ^ + ((uint32_t)Td4[(t0 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t3 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t2) & 0xff]) ^ rk[1]; + PUTU32(out + 4, s1); + s2 = ((uint32_t)Td4[(t2 >> 24)] << 24) ^ + ((uint32_t)Td4[(t1 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t0 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t3) & 0xff]) ^ rk[2]; + PUTU32(out + 8, s2); + s3 = ((uint32_t)Td4[(t3 >> 24)] << 24) ^ + ((uint32_t)Td4[(t2 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t1 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t0) & 0xff]) ^ rk[3]; + PUTU32(out + 12, s3); +} + +#else + +#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) + +static int hwaes_capable(void) { + return CRYPTO_is_ARMv8_AES_capable(); +} + +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); + +#else + +static int hwaes_capable(void) { + return 0; +} + +static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) { + abort(); +} + +static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) { + abort(); +} + +static void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} + +static void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} + +#endif + + +/* 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) { + if (hwaes_capable()) { + aes_v8_encrypt(in, out, key); + } else { + 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) { + if (hwaes_capable()) { + aes_v8_decrypt(in, out, key); + } else { + 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) { + if (hwaes_capable()) { + return aes_v8_set_encrypt_key(key, bits, aeskey); + } else { + 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) { + if (hwaes_capable()) { + return aes_v8_set_decrypt_key(key, bits, aeskey); + } else { + return asm_AES_set_decrypt_key(key, bits, aeskey); + } +} + +#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86 && !OPENSSL_X86_64 && !OPENSSL_ARM) */ diff --git a/external/boringssl/crypto/aes/aes_test.cc b/external/boringssl/crypto/aes/aes_test.cc new file mode 100644 index 0000000000..e488d81d11 --- /dev/null +++ b/external/boringssl/crypto/aes/aes_test.cc @@ -0,0 +1,102 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + + +static bool TestAES(const uint8_t *key, size_t key_len, + const uint8_t plaintext[AES_BLOCK_SIZE], + const uint8_t ciphertext[AES_BLOCK_SIZE]) { + AES_KEY aes_key; + if (AES_set_encrypt_key(key, key_len * 8, &aes_key) != 0) { + fprintf(stderr, "AES_set_encrypt_key failed\n"); + return false; + } + + // Test encryption. + uint8_t block[AES_BLOCK_SIZE]; + AES_encrypt(plaintext, block, &aes_key); + if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_encrypt gave the wrong output\n"); + return false; + } + + // Test in-place encryption. + memcpy(block, plaintext, AES_BLOCK_SIZE); + AES_encrypt(block, block, &aes_key); + if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_encrypt gave the wrong output\n"); + return false; + } + + if (AES_set_decrypt_key(key, key_len * 8, &aes_key) != 0) { + fprintf(stderr, "AES_set_decrypt_key failed\n"); + return false; + } + + // Test decryption. + AES_decrypt(ciphertext, block, &aes_key); + if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_decrypt gave the wrong output\n"); + return false; + } + + // Test in-place decryption. + memcpy(block, ciphertext, AES_BLOCK_SIZE); + AES_decrypt(block, block, &aes_key); + if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_decrypt gave the wrong output\n"); + return false; + } + return true; +} + +int main() { + CRYPTO_library_init(); + + // Test vectors from FIPS-197, Appendix C. + if (!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + 128 / 8, + (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + (const uint8_t *)"\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" + "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a") || + !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17", + 192 / 8, + (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + (const uint8_t *)"\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" + "\x6e\xaf\x70\xa0\xec\x0d\x71\x91") || + !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + 256 / 8, + (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + (const uint8_t *)"\x8e\xa2\xb7\xca\x51\x67\x45\xbf" + "\xea\xfc\x49\x90\x4b\x49\x60\x89")) { + return false; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/aes/asm/aes-586.pl.REMOVED.git-id b/external/boringssl/crypto/aes/asm/aes-586.pl.REMOVED.git-id new file mode 100644 index 0000000000..f65bf1199c --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aes-586.pl.REMOVED.git-id @@ -0,0 +1 @@ +6e8a6a806c460f62e0e156242c5a48e712a3d676 \ No newline at end of file diff --git a/external/boringssl/crypto/aes/asm/aes-armv4.pl b/external/boringssl/crypto/aes/asm/aes-armv4.pl new file mode 100644 index 0000000000..a60ed4cfa0 --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aes-armv4.pl @@ -0,0 +1,1244 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + 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 +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +#endif + +.text +#if __ARM_ARCH__<7 +.code 32 +#else +.syntax unified +# if defined(__thumb2__) && !defined(__APPLE__) +.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 +.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} +#ifdef __APPLE__ + adr $tbl,AES_Te +#else + sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te +#endif + mov $rounds,r0 @ inp + mov $key,r2 +#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 +.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} + mov $rounds,r0 @ inp + mov lr,r1 @ bits + mov $key,r2 @ key + +#ifdef __APPLE__ + adr $tbl,AES_Te+1024 @ Te4 +#else + sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 +#endif + +#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 __ARM_ARCH__>=5 + ret @ bx lr +#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 +.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 +.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 +.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} +#ifdef __APPLE__ + adr $tbl,AES_Td +#else + sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td +#endif + mov $rounds,r0 @ inp + mov $key,r2 +#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 " +.align 2 + +#endif +___ + +$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4 +$code =~ s/\bret\b/bx\tlr/gm; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/aes/asm/aes-x86_64.pl b/external/boringssl/crypto/aes/asm/aes-x86_64.pl new file mode 100644 index 0000000000..4b6e1b440f --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aes-x86_64.pl @@ -0,0 +1,2805 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 " +.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->RipRsp + + 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->RipRsp + + 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/external/boringssl/crypto/aes/asm/aesni-x86.pl b/external/boringssl/crypto/aes/asm/aesni-x86.pl new file mode 100644 index 0000000000..9b2e37aafb --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aesni-x86.pl @@ -0,0 +1,2525 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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 +# Silvermont 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); + +&external_label("OPENSSL_ia32cap_P"); +&static_label("key_const"); + +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 extension +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"); } + &pxor ($rndkey0,$rndkey0); # clear register bank + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,"eax"),$inout0); + &pxor ($inout0,$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"); } + &pxor ($rndkey0,$rndkey0); # clear register bank + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,"eax"),$inout0); + &pxor ($inout0,$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); + &$movekey ($rndkey0,&QWP(0,$key,$rounds)); + &add ($rounds,16); + &jmp (&label("_aesni_${p}rypt6_inner")); + + &set_label("${p}6_loop",16); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + &set_label("_aesni_${p}rypt6_inner"); + 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"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&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); + + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&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); + + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&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"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(32,"esp"),"xmm0"); # clear stack + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(48,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(64,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &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"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack + &pxor ("xmm3","xmm3"); + &movdqa (&QWP(16*1,"esp"),"xmm0"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(16*2,"esp"),"xmm0"); + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(16*3,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(16*4,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &movdqa (&QWP(16*5,"esp"),"xmm0"); + &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"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack + &pxor ("xmm3","xmm3"); + &movdqa (&QWP(16*1,"esp"),"xmm0"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(16*2,"esp"),"xmm0"); + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(16*3,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(16*4,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &movdqa (&QWP(16*5,"esp"),"xmm0"); + &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); + &pxor ($inout0,$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_clear_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); + &pxor ($inout1,$inout1); + &movups (&QWP(0x20,$out),$inout2); + &pxor ($inout2,$inout2); + &movups (&QWP(0x30,$out),$inout3); + &pxor ($inout3,$inout3); + &lea ($out,&DWP(0x40,$out)); + &movaps ($inout0,$inout4); + &pxor ($inout4,$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); + &pxor ($inout1,$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); + &pxor ($inout2,$inout2); + &movups (&QWP(0x10,$out),$inout1); + &pxor ($inout1,$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); + &pxor ($inout1,$inout1); + &xorps ($inout3,$rndkey0); + &movups (&QWP(0x20,$out),$inout2); + &pxor ($inout2,$inout2); + &lea ($out,&DWP(0x30,$out)); + &movaps ($inout0,$inout3); + &pxor ($inout3,$inout3); + &sub ($len,0x40); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_clear_tail_collected",16); + &pxor ($inout1,$inout1); + &pxor ($inout2,$inout2); + &pxor ($inout3,$inout3); + &pxor ($inout4,$inout4); +&set_label("cbc_dec_tail_collected"); + &and ($len,15); + &jnz (&label("cbc_dec_tail_partial")); + &movups (&QWP(0,$out),$inout0); + &pxor ($rndkey0,$rndkey0); + &jmp (&label("cbc_ret")); + +&set_label("cbc_dec_tail_partial",16); + &movaps (&QWP(0,"esp"),$inout0); + &pxor ($rndkey0,$rndkey0); + &mov ("ecx",16); + &mov ($inp,"esp"); + &sub ("ecx",$len); + &data_word(0xA4F3F689); # rep movsb + &movdqa (&QWP(0,"esp"),$inout0); + +&set_label("cbc_ret"); + &mov ("esp",&DWP(16,"esp")); # pull original %esp + &mov ($key_,&wparam(4)); + &pxor ($inout0,$inout0); + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,$key_),$ivec); # output IV + &pxor ($ivec,$ivec); +&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"); + &push ("ebp"); + &push ("ebx"); + &test ("eax","eax"); + &jz (&label("bad_pointer")); + &test ($key,$key); + &jz (&label("bad_pointer")); + + &call (&label("pic")); +&set_label("pic"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("key_const")."-".&label("pic"),"ebx")); + + &picmeup("ebp","OPENSSL_ia32cap_P","ebx",&label("key_const")); + &movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey + &xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0 + &mov ("ebp",&DWP(4,"ebp")); + &lea ($key,&DWP(16,$key)); + &and ("ebp",1<<28|1<<11); # AVX and XOP bits + &cmp ($rounds,256); + &je (&label("14rounds")); + &cmp ($rounds,192); + &je (&label("12rounds")); + &cmp ($rounds,128); + &jne (&label("bad_keybits")); + +&set_label("10rounds",16); + &cmp ("ebp",1<<28); + &je (&label("10rounds_alt")); + + &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); + + &jmp (&label("good_key")); + +&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("10rounds_alt",16); + &movdqa ("xmm5",&QWP(0x00,"ebx")); + &mov ($rounds,8); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &movdqa ("xmm2","xmm0"); + &movdqu (&QWP(-16,$key),"xmm0"); + +&set_label("loop_key128"); + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + &pslld ("xmm4",1); + &lea ($key,&DWP(16,$key)); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(-16,$key),"xmm0"); + &movdqa ("xmm2","xmm0"); + + &dec ($rounds); + &jnz (&label("loop_key128")); + + &movdqa ("xmm4",&QWP(0x30,"ebx")); + + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + &pslld ("xmm4",1); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(0,$key),"xmm0"); + + &movdqa ("xmm2","xmm0"); + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(16,$key),"xmm0"); + + &mov ($rounds,9); + &mov (&DWP(96,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("12rounds",16); + &movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey + &cmp ("ebp",1<<28); + &je (&label("12rounds_alt")); + + &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); + + &jmp (&label("good_key")); + +&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("12rounds_alt",16); + &movdqa ("xmm5",&QWP(0x10,"ebx")); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &mov ($rounds,8); + &movdqu (&QWP(-16,$key),"xmm0"); + +&set_label("loop_key192"); + &movq (&QWP(0,$key),"xmm2"); + &movdqa ("xmm1","xmm2"); + &pshufb ("xmm2","xmm5"); + &aesenclast ("xmm2","xmm4"); + &pslld ("xmm4",1); + &lea ($key,&DWP(24,$key)); + + &movdqa ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm0","xmm3"); + + &pshufd ("xmm3","xmm0",0xff); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + + &pxor ("xmm0","xmm2"); + &pxor ("xmm2","xmm3"); + &movdqu (&QWP(-16,$key),"xmm0"); + + &dec ($rounds); + &jnz (&label("loop_key192")); + + &mov ($rounds,11); + &mov (&DWP(32,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("14rounds",16); + &movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey + &lea ($key,&DWP(16,$key)); + &cmp ("ebp",1<<28); + &je (&label("14rounds_alt")); + + &mov ($rounds,13); + &$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"); + + &jmp (&label("good_key")); + +&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("14rounds_alt",16); + &movdqa ("xmm5",&QWP(0x00,"ebx")); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &mov ($rounds,7); + &movdqu (&QWP(-32,$key),"xmm0"); + &movdqa ("xmm1","xmm2"); + &movdqu (&QWP(-16,$key),"xmm2"); + +&set_label("loop_key256"); + &pshufb ("xmm2","xmm5"); + &aesenclast ("xmm2","xmm4"); + + &movdqa ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm0","xmm3"); + &pslld ("xmm4",1); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(0,$key),"xmm0"); + + &dec ($rounds); + &jz (&label("done_key256")); + + &pshufd ("xmm2","xmm0",0xff); + &pxor ("xmm3","xmm3"); + &aesenclast ("xmm2","xmm3"); + + &movdqa ("xmm3","xmm1") + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm1","xmm3"); + + &pxor ("xmm2","xmm1"); + &movdqu (&QWP(16,$key),"xmm2"); + &lea ($key,&DWP(32,$key)); + &movdqa ("xmm1","xmm2"); + &jmp (&label("loop_key256")); + +&set_label("done_key256"); + &mov ($rounds,13); + &mov (&DWP(16,$key),$rounds); + +&set_label("good_key"); + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &xor ("eax","eax"); + &pop ("ebx"); + &pop ("ebp"); + &ret (); + +&set_label("bad_pointer",4); + &mov ("eax",-1); + &pop ("ebx"); + &pop ("ebp"); + &ret (); +&set_label("bad_keybits",4); + &pxor ("xmm0","xmm0"); + &mov ("eax",-2); + &pop ("ebx"); + &pop ("ebp"); + &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"); + + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &xor ("eax","eax"); # return success +&set_label("dec_key_ret"); + &ret (); +&function_end_B("${PREFIX}_set_decrypt_key"); + +&set_label("key_const",64); +&data_word(0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d); +&data_word(0x04070605,0x04070605,0x04070605,0x04070605); +&data_word(1,1,1,1); +&data_word(0x1b,0x1b,0x1b,0x1b); +&asciz("AES for Intel AES-NI, CRYPTOGAMS by "); + +&asm_finish(); diff --git a/external/boringssl/crypto/aes/asm/aesni-x86_64.pl.REMOVED.git-id b/external/boringssl/crypto/aes/asm/aesni-x86_64.pl.REMOVED.git-id new file mode 100644 index 0000000000..42ccd3e88c --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aesni-x86_64.pl.REMOVED.git-id @@ -0,0 +1 @@ +25ca574f6a2f90b04dccc0a7726df86772bcb996 \ No newline at end of file diff --git a/external/boringssl/crypto/aes/asm/aesv8-armx.pl b/external/boringssl/crypto/aes/asm/aesv8-armx.pl new file mode 100644 index 0000000000..121154a4b6 --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aesv8-armx.pl @@ -0,0 +1,1001 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 1.32 1.29 1.46 +# Cortex-A57(*) 1.95 0.85 0.93 +# Denver 1.96 0.86 0.80 +# +# (*) original 3.64/1.34/1.32 results were for r0p0 revision +# and are still same even for updated module; + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$prefix="aes_v8"; + +$code=<<___; +#include + +#if __ARM_MAX_ARCH__>=7 +.text +___ +$code.=<<___ if ($flavour =~ /64/); +#if !defined(__clang__) +.arch armv8-a+crypto +#endif +___ +$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 +.Lrcon: +.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,.Lrcon + 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 + aes$mc $inout,$inout + vld1.32 {$rndkey0},[$key],#16 + subs $rounds,$rounds,#2 + aes$e $inout,$rndkey1 + aes$mc $inout,$inout + vld1.32 {$rndkey1},[$key],#16 + b.gt .Loop_${dir}c + + aes$e $inout,$rndkey0 + aes$mc $inout,$inout + vld1.32 {$rndkey0},[$key] + 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); +my ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key); + +### 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 + + vld1.32 {$in0-$in1},[$key_] + add $key_,$key,#16 + add $key4,$key,#16*4 + add $key5,$key,#16*5 + aese $dat,q8 + aesmc $dat,$dat + add $key6,$key,#16*6 + add $key7,$key,#16*7 + b .Lenter_cbc_enc + +.align 4 +.Loop_cbc_enc: + aese $dat,q8 + aesmc $dat,$dat + vst1.8 {$ivec},[$out],#16 +.Lenter_cbc_enc: + aese $dat,q9 + aesmc $dat,$dat + aese $dat,$in0 + aesmc $dat,$dat + vld1.32 {q8},[$key4] + cmp $rounds,#4 + aese $dat,$in1 + aesmc $dat,$dat + vld1.32 {q9},[$key5] + b.eq .Lcbc_enc192 + + aese $dat,q8 + aesmc $dat,$dat + vld1.32 {q8},[$key6] + aese $dat,q9 + aesmc $dat,$dat + vld1.32 {q9},[$key7] + nop + +.Lcbc_enc192: + 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 + 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_] // re-pre-load rndkey[1] + aese $dat,q14 + aesmc $dat,$dat + aese $dat,q15 + veor $ivec,$dat,$rndlast + b.hs .Loop_cbc_enc + + vst1.8 {$ivec},[$out],#16 + 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 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_cbc_dec + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + veor $tmp0,$ivec,$rndlast + subs $len,$len,#0x30 + veor $tmp1,$in0,$rndlast + mov.lo x6,$len // x6, $cnt, is zero at this point + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + veor $tmp2,$in1,$rndlast + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat2 + // are loaded with last "words" + vorr $ivec,$in2,$in2 + mov $key_,$key + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + vld1.8 {$in0},[$inp],#16 + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aesd $dat0,q15 + aesd $dat1,q15 + aesd $dat2,q15 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + add $cnt,$rounds,#2 + veor $tmp0,$tmp0,$dat0 + veor $tmp1,$tmp1,$dat1 + veor $dat2,$dat2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vorr $dat0,$in0,$in0 + vst1.8 {$tmp1},[$out],#16 + vorr $dat1,$in1,$in1 + vst1.8 {$dat2},[$out],#16 + vorr $dat2,$in2,$in2 + b.hs .Loop3x_cbc_dec + + cmn $len,#0x30 + b.eq .Lcbc_done + nop + +.Lcbc_dec_tail: + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lcbc_dec_tail + + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + cmn $len,#0x20 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + veor $tmp1,$ivec,$rndlast + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + 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 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_ctr32 + + aese $dat0,q8 + aesmc $tmp0,$dat0 + aese $dat1,q8 + aesmc $tmp1,$dat1 + vld1.8 {$in0},[$inp],#16 + vorr $dat0,$ivec,$ivec + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + vorr $dat1,$ivec,$ivec + aese $tmp0,q9 + aesmc $tmp0,$tmp0 + aese $tmp1,q9 + aesmc $tmp1,$tmp1 + vld1.8 {$in2},[$inp],#16 + mov $key_,$key + aese $dat2,q9 + aesmc $tmp2,$dat2 + vorr $dat2,$ivec,$ivec + add $tctr0,$ctr,#1 + aese $tmp0,q12 + aesmc $tmp0,$tmp0 + aese $tmp1,q12 + aesmc $tmp1,$tmp1 + veor $in0,$in0,$rndlast + add $tctr1,$ctr,#2 + aese $tmp2,q12 + aesmc $tmp2,$tmp2 + veor $in1,$in1,$rndlast + add $ctr,$ctr,#3 + aese $tmp0,q13 + aesmc $tmp0,$tmp0 + aese $tmp1,q13 + aesmc $tmp1,$tmp1 + veor $in2,$in2,$rndlast + rev $tctr0,$tctr0 + aese $tmp2,q13 + aesmc $tmp2,$tmp2 + vmov.32 ${dat0}[3], $tctr0 + rev $tctr1,$tctr1 + aese $tmp0,q14 + aesmc $tmp0,$tmp0 + aese $tmp1,q14 + aesmc $tmp1,$tmp1 + vmov.32 ${dat1}[3], $tctr1 + rev $tctr2,$ctr + aese $tmp2,q14 + aesmc $tmp2,$tmp2 + vmov.32 ${dat2}[3], $tctr2 + subs $len,$len,#3 + aese $tmp0,q15 + aese $tmp1,q15 + aese $tmp2,q15 + + veor $in0,$in0,$tmp0 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + vst1.8 {$in0},[$out],#16 + veor $in1,$in1,$tmp1 + mov $cnt,$rounds + vst1.8 {$in1},[$out],#16 + veor $in2,$in2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + 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 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.32 {q9},[$key_],#16 + b.gt .Lctr32_tail + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.8 {$in0},[$inp],$step + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + vld1.8 {$in1},[$inp] + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + veor $in0,$in0,$rndlast + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + 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/external/boringssl/crypto/aes/asm/bsaes-armv7.pl b/external/boringssl/crypto/aes/asm/bsaes-armv7.pl new file mode 100644 index 0000000000..22362f515d --- /dev/null +++ b/external/boringssl/crypto/aes/asm/bsaes-armv7.pl @@ -0,0 +1,2505 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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 +# . 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)... +# +# + +# April-August 2013 +# +# Add CBC, CTR and XTS subroutines, adapt for kernel use. +# +# + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + 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.=<<___; +#ifndef __KERNEL__ +# include + +# 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__ +# define __ARM_MAX_ARCH__ 7 +#endif + +#ifdef __thumb__ +# define adrl adr +#endif + +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.text +.syntax unified @ ARMv7-capable assembler is expected to handle this +#if defined(__thumb2__) && !defined(__APPLE__) +.thumb +#else +.code 32 +#endif + +.type _bsaes_decrypt8,%function +.align 4 +_bsaes_decrypt8: + adr $const,_bsaes_decrypt8 + vldmia $key!, {@XMM[9]} @ round 0 key +#ifdef __APPLE__ + adr $const,.LM0ISR +#else + add $const,$const,#.LM0ISR-_bsaes_decrypt8 +#endif + + 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 " +.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 +#ifdef __APPLE__ + adr $const,.LM0SR +#else + sub $const,$const,#_bsaes_encrypt8-.LM0SR +#endif + + 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 +#ifdef __APPLE__ + adr $const,.LM0 +#else + sub $const,$const,#_bsaes_key_convert-.LM0 +#endif + 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 +.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 +.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 +.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 +.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 +.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 +.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 +#ifdef __APPLE__ + mov $ctr, #:lower16:(.LREVM0SR-.LM0) + add $ctr, $const, $ctr +#else + add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr +#endif + 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 +#ifdef __APPLE__ + mov $const, #:lower16:(.LREVM0SR-.LSR) + sub $const, $ctr, $const +#else + sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants +#endif + + 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] @ 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] @ 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 +.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 +.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 + +#ifndef XTS_CHAIN_TWEAK + tst $len, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne $len, #0x10 @ subtract another 16 bytes +#endif + 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 +___ + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/aes/asm/bsaes-x86_64.pl b/external/boringssl/crypto/aes/asm/bsaes-x86_64.pl new file mode 100644 index 0000000000..3f7d33c45b --- /dev/null +++ b/external/boringssl/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... +# +# + +$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->RipRsp + + 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/external/boringssl/crypto/aes/asm/vpaes-x86.pl b/external/boringssl/crypto/aes/asm/vpaes-x86.pl new file mode 100644 index 0000000000..2ba149c3f9 --- /dev/null +++ b/external/boringssl/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). +# +# + +$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/external/boringssl/crypto/aes/asm/vpaes-x86_64.pl b/external/boringssl/crypto/aes/asm/vpaes-x86_64.pl new file mode 100644 index 0000000000..f2ef318fae --- /dev/null +++ b/external/boringssl/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). +# +# + +$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->RipRsp + + 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/external/boringssl/crypto/aes/internal.h b/external/boringssl/crypto/aes/internal.h new file mode 100644 index 0000000000..3dc5c6379c --- /dev/null +++ b/external/boringssl/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 + +#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/external/boringssl/crypto/aes/mode_wrappers.c b/external/boringssl/crypto/aes/mode_wrappers.c new file mode 100644 index 0000000000..4929920f00 --- /dev/null +++ b/external/boringssl/crypto/aes/mode_wrappers.c @@ -0,0 +1,112 @@ +/* ==================================================================== + * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include + +#include "../modes/internal.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) { + unsigned num_u = (unsigned)(*num); + CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u, + (block128_f)AES_encrypt); + *num = (int)num_u; +} + +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) { + unsigned num_u = (unsigned)(*num); + CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc, + (block128_f)AES_encrypt); + *num = (int)num_u; +} diff --git a/external/boringssl/crypto/asn1/CMakeLists.txt b/external/boringssl/crypto/asn1/CMakeLists.txt new file mode 100644 index 0000000000..90fe01f5ea --- /dev/null +++ b/external/boringssl/crypto/asn1/CMakeLists.txt @@ -0,0 +1,54 @@ +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_lib.c + asn1_par.c + asn_pack.c + f_enum.c + f_int.c + f_string.c + t_bitst.c + tasn_dec.c + tasn_enc.c + tasn_fre.c + tasn_new.c + tasn_typ.c + tasn_utl.c + x_bignum.c + x_long.c +) + +if(ENABLE_TESTS) +add_executable( + asn1_test + + asn1_test.cc + + $ +) + +target_link_libraries(asn1_test crypto) +add_dependencies(all_tests asn1_test) +endif() diff --git a/external/boringssl/crypto/asn1/a_bitstr.c b/external/boringssl/crypto/asn1/a_bitstr.c new file mode 100644 index 0000000000..2705ea5687 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_bitstr.c @@ -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.] */ + +#include + +#include + +#include +#include + +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, 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, 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, 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 + */ +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, 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/external/boringssl/crypto/asn1/a_bool.c b/external/boringssl/crypto/asn1/a_bool.c new file mode 100644 index 0000000000..64a079ec4b --- /dev/null +++ b/external/boringssl/crypto/asn1/a_bool.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 + +#include +#include + +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, i); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_bytes.c b/external/boringssl/crypto/asn1/a_bytes.c new file mode 100644 index 0000000000..e6b2f2e9a1 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_bytes.c @@ -0,0 +1,308 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + +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, 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)) { + s = (unsigned char *)OPENSSL_malloc((int)len + 1); + if (s == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + if (ret->data != NULL) + OPENSSL_free(ret->data); + } 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, 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 + * , 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, c->error); + if (os != NULL) + ASN1_STRING_free(os); + if (b.data != NULL) + OPENSSL_free(b.data); + return (0); +} diff --git a/external/boringssl/crypto/asn1/a_d2i_fp.c b/external/boringssl/crypto/asn1/a_d2i_fp.c new file mode 100644 index 0000000000..b544971911 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_d2i_fp.c @@ -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.] */ + +#include + +#include + +#include +#include +#include + +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, 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, 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 +#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) +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, 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, 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_R_NOT_ENOUGH_DATA); + goto err; + } + if (i > 0) { + if (len + i < len) { + OPENSSL_PUT_ERROR(ASN1, 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) { + uint32_t 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_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)) { + size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; + want -= (len - off); + if (want > INT_MAX /* BIO_read takes an int length */ || + len + want < len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + goto err; + } + while (want > 0) { + /* + * Read content in chunks of increasing size + * so we can return an error for EOF without + * having to allocate the entire content length + * in one go. + */ + size_t chunk = want > chunk_max ? chunk_max : want; + + if (!BUF_MEM_grow_clean(b, len + chunk)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + want -= chunk; + while (chunk > 0) { + i = BIO_read(in, &(b->data[len]), chunk); + if (i <= 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + /* + * This can't overflow because |len+want| didn't + * overflow. + */ + len += i; + chunk -= i; + } + if (chunk_max < INT_MAX/2) + chunk_max *= 2; + } + } + if (off + c.slen < off) { + OPENSSL_PUT_ERROR(ASN1, 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_R_TOO_LONG); + goto err; + } + + *pb = b; + return off; + err: + if (b != NULL) + BUF_MEM_free(b); + return -1; +} diff --git a/external/boringssl/crypto/asn1/a_dup.c b/external/boringssl/crypto/asn1/a_dup.c new file mode 100644 index 0000000000..57394f58c4 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_dup.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +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, 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, ERR_R_MALLOC_FAILURE); + return (NULL); + } + p = b; + ret = ASN1_item_d2i(NULL, &p, i, it); + OPENSSL_free(b); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_enum.c b/external/boringssl/crypto/asn1/a_enum.c new file mode 100644 index 0000000000..0b95fc95e8 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_enum.c @@ -0,0 +1,181 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +/* + * 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, 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, 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, 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_R_BN_LIB); + else if (ai->type == V_ASN1_NEG_ENUMERATED) + BN_set_negative(ret, 1); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_gentm.c b/external/boringssl/crypto/asn1/a_gentm.c new file mode 100644 index 0000000000..ee6b3db54c --- /dev/null +++ b/external/boringssl/crypto/asn1/a_gentm.c @@ -0,0 +1,256 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +#include "asn1_locl.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, 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/external/boringssl/crypto/asn1/a_i2d_fp.c b/external/boringssl/crypto/asn1/a_i2d_fp.c new file mode 100644 index 0000000000..486207ed2e --- /dev/null +++ b/external/boringssl/crypto/asn1/a_i2d_fp.c @@ -0,0 +1,147 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +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, 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, void *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, 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, 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, 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/external/boringssl/crypto/asn1/a_int.c b/external/boringssl/crypto/asn1/a_int.c new file mode 100644 index 0000000000..38a01bcb88 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_int.c @@ -0,0 +1,460 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +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 (ret == 1 && i == 0) + neg = 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 && i > 1) { + *(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, 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, 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, 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, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + if (BN_is_negative(bn) && !BN_is_zero(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, 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_R_BN_LIB); + else if (ai->type == V_ASN1_NEG_INTEGER) + BN_set_negative(ret, 1); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_mbstr.c b/external/boringssl/crypto/asn1/a_mbstr.c new file mode 100644 index 0000000000..30fff82a7f --- /dev/null +++ b/external/boringssl/crypto/asn1/a_mbstr.c @@ -0,0 +1,409 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +static int 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_R_INVALID_BMPSTRING_LENGTH); + return -1; + } + nchar = len >> 1; + break; + + case MBSTRING_UNIV: + if (len & 3) { + OPENSSL_PUT_ERROR(ASN1, 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_R_INVALID_UTF8STRING); + return -1; + } + break; + + case MBSTRING_ASC: + nchar = len; + break; + + default: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + + if ((minsize > 0) && (nchar < minsize)) { + OPENSSL_PUT_ERROR(ASN1, 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_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_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, 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, 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, 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/external/boringssl/crypto/asn1/a_object.c b/external/boringssl/crypto/asn1/a_object.c new file mode 100644 index 0000000000..10f3839876 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_object.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 + +#include +#include + +#include +#include +#include + +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, ASN1_R_FIRST_NUM_TOO_LARGE); + goto err; + } + + if (num <= 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER); + goto err; + } + c = *(p++); + num--; + for (;;) { + if (num <= 0) + break; + if ((c != '.') && (c != ' ')) { + OPENSSL_PUT_ERROR(ASN1, 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, 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, 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, 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, "", 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, 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, 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, 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, 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, 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/external/boringssl/crypto/asn1/a_octet.c b/external/boringssl/crypto/asn1/a_octet.c new file mode 100644 index 0000000000..2e74d6bfdf --- /dev/null +++ b/external/boringssl/crypto/asn1/a_octet.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +ASN1_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/external/boringssl/crypto/asn1/a_print.c b/external/boringssl/crypto/asn1/a_print.c new file mode 100644 index 0000000000..aee54fa496 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_print.c @@ -0,0 +1,121 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +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/external/boringssl/crypto/asn1/a_strnid.c b/external/boringssl/crypto/asn1/a_strnid.c new file mode 100644 index 0000000000..c558bce6c1 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_strnid.c @@ -0,0 +1,309 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include /* For bsearch */ +#include + +#include +#include +#include + +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, 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, ERR_R_MALLOC_FAILURE); + return 0; + } + tmp->flags = flags | STABLE_FLAGS_MALLOC; + tmp->nid = nid; + tmp->minsize = tmp->maxsize = -1; + 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/external/boringssl/crypto/asn1/a_time.c b/external/boringssl/crypto/asn1/a_time.c new file mode 100644 index 0000000000..4391092ac1 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_time.c @@ -0,0 +1,217 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "asn1_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, 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_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/external/boringssl/crypto/asn1/a_type.c b/external/boringssl/crypto/asn1/a_type.c new file mode 100644 index 0000000000..734ff8b4d4 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_type.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 + +#include +#include +#include +#include + +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_BOOLEAN: + result = a->value.boolean - b->value.boolean; + break; + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + case V_ASN1_BIT_STRING: + case V_ASN1_OCTET_STRING: + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_OTHER: + default: + result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr, + (ASN1_STRING *)b->value.ptr); + break; + } + + return result; +} diff --git a/external/boringssl/crypto/asn1/a_utctm.c b/external/boringssl/crypto/asn1/a_utctm.c new file mode 100644 index 0000000000..5a55bd24df --- /dev/null +++ b/external/boringssl/crypto/asn1/a_utctm.c @@ -0,0 +1,335 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +#include "asn1_locl.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, ERR_R_NESTED_ASN1_ERROR); + return (NULL); + } + if (!ASN1_UTCTIME_check(ret)) { + OPENSSL_PUT_ERROR(ASN1, 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, 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, &ttm, &stm)) + 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/external/boringssl/crypto/asn1/a_utf8.c b/external/boringssl/crypto/asn1/a_utf8.c new file mode 100644 index 0000000000..1702768668 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_utf8.c @@ -0,0 +1,234 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +/* 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/external/boringssl/crypto/asn1/asn1_lib.c b/external/boringssl/crypto/asn1/asn1_lib.c new file mode 100644 index 0000000000..b637e795b0 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_lib.c @@ -0,0 +1,505 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +/* Cross-module errors from crypto/x509/i2d_pr.c. */ +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE); + +/* Cross-module errors from crypto/x509/algorithm.c. */ +OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED); +OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM); +OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE); +/* + * Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove + * these once asn1_gen.c is gone. + */ +OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE); +OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER); +OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER); +OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR); +OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE); +OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG); +OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE); + +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, + long 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; + } + + /* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */ + if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL) + goto err; + + *ptag = tag; + *pclass = xclass; + if (!asn1_get_length(&p, &inf, plength, 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_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_R_HEADER_TOO_LONG); + return (0x80); +} + +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, + long max) +{ + const unsigned char *p = *pp; + unsigned long ret = 0; + unsigned long 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(ret) || max < (long)i) + return 0; + while (i-- > 0) { + ret <<= 8L; + ret |= *(p++); + } + } 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, 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, 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); +} + +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/external/boringssl/crypto/asn1/asn1_locl.h b/external/boringssl/crypto/asn1/asn1_locl.h new file mode 100644 index 0000000000..982bfd6036 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_locl.h @@ -0,0 +1,63 @@ +/* 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); diff --git a/external/boringssl/crypto/asn1/asn1_par.c b/external/boringssl/crypto/asn1/asn1_par.c new file mode 100644 index 0000000000..b1a01edaee --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_par.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 + + +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", "", "UTF8STRING", "", /* 10-13 */ + "", "", "SEQUENCE", "SET", /* 15-17 */ + "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */ + "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24 + */ + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */ + "UNIVERSALSTRING", "", "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/external/boringssl/crypto/asn1/asn1_test.cc b/external/boringssl/crypto/asn1/asn1_test.cc new file mode 100644 index 0000000000..8b024427a2 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_test.cc @@ -0,0 +1,81 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include "../test/scoped_types.h" + + +// kTag128 is an ASN.1 structure with a universal tag with number 128. +static const uint8_t kTag128[] = { + 0x1f, 0x81, 0x00, 0x01, 0x00, +}; + +// kTag258 is an ASN.1 structure with a universal tag with number 258. +static const uint8_t kTag258[] = { + 0x1f, 0x82, 0x02, 0x01, 0x00, +}; + +static_assert(V_ASN1_NEG_INTEGER == 258, + "V_ASN1_NEG_INTEGER changed. Update kTag258 to collide with it."); + +// kTagOverflow is an ASN.1 structure with a universal tag with number 2^35-1, +// which will not fit in an int. +static const uint8_t kTagOverflow[] = { + 0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, +}; + +static bool TestLargeTags() { + const uint8_t *p = kTag258; + ScopedASN1_TYPE obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258))); + if (obj) { + fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type); + return false; + } + ERR_clear_error(); + + p = kTagOverflow; + obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow))); + if (obj) { + fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type); + return false; + } + ERR_clear_error(); + + p = kTag128; + obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128))); + if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 || + obj->value.asn1_string->data[0] != 0) { + fprintf(stderr, "Failed to parse value with tag 128.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +int main() { + CRYPTO_library_init(); + + if (!TestLargeTags()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/asn1/asn_pack.c b/external/boringssl/crypto/asn1/asn_pack.c new file mode 100644 index 0000000000..eff54e55c6 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn_pack.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 + +#include +#include + +/* 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, 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_R_ENCODE_ERROR); + return NULL; + } + if (!octmp->data) { + OPENSSL_PUT_ERROR(ASN1, 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_R_DECODE_ERROR); + return ret; +} diff --git a/external/boringssl/crypto/asn1/charmap.pl b/external/boringssl/crypto/asn1/charmap.pl new file mode 100644 index 0000000000..71bc7b8bd7 --- /dev/null +++ b/external/boringssl/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 < + +#include +#include + +/* 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, 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, 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, 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, ASN1_R_SHORT_LINE); + } + if (s != NULL) + OPENSSL_free(s); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/f_int.c b/external/boringssl/crypto/asn1/f_int.c new file mode 100644 index 0000000000..60c0f2f2be --- /dev/null +++ b/external/boringssl/crypto/asn1/f_int.c @@ -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.] */ + +#include + +#include +#include + +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, 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, 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, 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, ASN1_R_SHORT_LINE); + } + if (s != NULL) + OPENSSL_free(s); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/f_string.c b/external/boringssl/crypto/asn1/f_string.c new file mode 100644 index 0000000000..ec9cb83d17 --- /dev/null +++ b/external/boringssl/crypto/asn1/f_string.c @@ -0,0 +1,196 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +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, 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, 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, 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, ASN1_R_SHORT_LINE); + } + if (s != NULL) + OPENSSL_free(s); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/t_bitst.c b/external/boringssl/crypto/asn1/t_bitst.c new file mode 100644 index 0000000000..e754ca73a9 --- /dev/null +++ b/external/boringssl/crypto/asn1/t_bitst.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 + +#include + +#include + +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/external/boringssl/crypto/asn1/tasn_dec.c b/external/boringssl/crypto/asn1/tasn_dec.c new file mode 100644 index 0000000000..616b587c37 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_dec.c @@ -0,0 +1,1219 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include + +#include "../internal.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; + int combine = aclass & ASN1_TFLG_COMBINE; + 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_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_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_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_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_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_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_R_NESTED_ASN1_ERROR); + goto err; + + case ASN1_ITYPE_CHOICE: + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + + if (*pval) { + /* Free up and zero CHOICE value if initialised */ + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + tt = it->templates + i; + pchptr = asn1_get_field_ptr(pval, tt); + ASN1_template_free(pchptr, tt); + asn1_set_choice_selector(pval, -1, it); + } + } else if (!ASN1_item_ex_new(pval, it)) { + OPENSSL_PUT_ERROR(ASN1, 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_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_R_NO_MATCHING_CHOICE_TYPE); + goto err; + } + + asn1_set_choice_selector(pval, i, it); + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) + goto auxerr; + *in = p; + 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_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_R_SEQUENCE_NOT_CONSTRUCTED); + goto err; + } + + if (!*pval && !ASN1_item_ex_new(pval, it)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + + /* Free up and zero any ADB found */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + if (tt->flags & ASN1_TFLG_ADB_MASK) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } + } + + /* 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_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_R_MISSING_EOC); + goto err; + } + /* Check all data read */ + if (!seq_nolen && len) { + OPENSSL_PUT_ERROR(ASN1, 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_R_FIELD_MISSING); + goto err; + } + } + /* Save encoding */ + if (!asn1_enc_save(pval, *in, p - *in, it)) + goto auxerr; + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) + goto auxerr; + *in = p; + return 1; + + default: + return 0; + } + auxerr: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); + err: + if (combine == 0) + 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_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) + return -1; + if (!cst) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); + return 0; + } + /* We've found the field so it can't be OPTIONAL now */ + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, 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_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_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_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, 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_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_R_NESTED_ASN1_ERROR); + goto err; + } + len -= p - q; + if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (sk_eoc) { + OPENSSL_PUT_ERROR(ASN1, 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_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, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, 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 = {0, NULL, 0 }; + const unsigned char *cont = NULL; + long len; + if (!pval) { + OPENSSL_PUT_ERROR(ASN1, 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_R_ILLEGAL_TAGGED_ANY); + return 0; + } + if (opt) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY); + return 0; + } + p = *in; + ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, + &p, inlen, -1, 0, 0, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, 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_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_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; + } + } 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_R_TYPE_NOT_PRIMITIVE); + return 0; + } + + /* Free any returned 'buf' content */ + free_cont = 1; + /* + * 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)) { + goto err; + } + len = buf.length; + /* Append a final null to string */ + if (!BUF_MEM_grow_clean(&buf, len + 1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + buf.data[len] = 0; + cont = (const unsigned char *)buf.data; + } else { + cont = p; + len = plen; + p += plen; + } + + /* We now have content length and type: translate into a structure */ + /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */ + 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_R_NULL_IS_WRONG_LENGTH); + goto err; + } + *pval = (ASN1_VALUE *)1; + break; + + case V_ASN1_BOOLEAN: + if (len != 1) { + OPENSSL_PUT_ERROR(ASN1, 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_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_R_BMPSTRING_IS_WRONG_LENGTH); + goto err; + } + if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { + OPENSSL_PUT_ERROR(ASN1, 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, 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, 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_R_NESTED_ASN1_ERROR); + return 0; + } + if (inf) + expected_eoc++; + else + p += plen; + len -= p - q; + } + if (expected_eoc) { + OPENSSL_PUT_ERROR(ASN1, 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_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_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_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_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, 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_R_TOO_LONG); + asn1_tlc_clear(ctx); + return 0; + } + } + } + + if (i & 0x80) { + OPENSSL_PUT_ERROR(ASN1, 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_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/external/boringssl/crypto/asn1/tasn_enc.c b/external/boringssl/crypto/asn1/tasn_enc.c new file mode 100644 index 0000000000..409d1388b2 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_enc.c @@ -0,0 +1,657 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +static int asn1_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_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/external/boringssl/crypto/asn1/tasn_fre.c b/external/boringssl/crypto/asn1/tasn_fre.c new file mode 100644 index 0000000000..609cb9f987 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_fre.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +static 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_refcount_dec_and_test_zero(pval, it)) + 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/external/boringssl/crypto/asn1/tasn_new.c b/external/boringssl/crypto/asn1/tasn_new.c new file mode 100644 index 0000000000..232fe46aaa --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_new.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 + +#include + +#include +#include +#include +#include + +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; + +#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_refcount_set_one(pval, 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, ERR_R_MALLOC_FAILURE); + ASN1_item_ex_free(pval, it); +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_pop_info(); +#endif + return 0; + + auxerr: + OPENSSL_PUT_ERROR(ASN1, 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, 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) + return 0; + + if (it->funcs) { + const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + if (pf->prim_new) + return pf->prim_new(pval, it); + } + + if (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/external/boringssl/crypto/asn1/tasn_typ.c b/external/boringssl/crypto/asn1/tasn_typ.c new file mode 100644 index 0000000000..daf02eae93 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_typ.c @@ -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.] */ + +#include + +#include + +/* Declarations for string types */ + +#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ + IMPLEMENT_ASN1_TYPE(sname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \ + sname *sname##_new(void) \ + { \ + return ASN1_STRING_type_new(V_##sname); \ + } \ + void sname##_free(sname *x) \ + { \ + ASN1_STRING_free(x); \ + } + +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_NULL); +IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL); + +IMPLEMENT_ASN1_TYPE(ASN1_OBJECT); + +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/external/boringssl/crypto/asn1/tasn_utl.c b/external/boringssl/crypto/asn1/tasn_utl.c new file mode 100644 index 0000000000..960cdbb7a5 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_utl.c @@ -0,0 +1,266 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "../internal.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; +} + +static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval, + const ASN1_ITEM *it) { + if (it->itype != ASN1_ITYPE_SEQUENCE && + it->itype != ASN1_ITYPE_NDEF_SEQUENCE) { + return NULL; + } + const ASN1_AUX *aux = it->funcs; + if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) { + return NULL; + } + return offset2ptr(*pval, aux->ref_offset); +} + +void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) { + CRYPTO_refcount_t *references = asn1_get_references(pval, it); + if (references != NULL) { + *references = 1; + } +} + +int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) { + CRYPTO_refcount_t *references = asn1_get_references(pval, it); + if (references != NULL) { + return CRYPTO_refcount_dec_and_test_zero(references); + } + return 1; +} + +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_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); + } + return NULL; +} diff --git a/external/boringssl/crypto/asn1/x_bignum.c b/external/boringssl/crypto/asn1/x_bignum.c new file mode 100644 index 0000000000..585d9d4a43 --- /dev/null +++ b/external/boringssl/crypto/asn1/x_bignum.c @@ -0,0 +1,153 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +/* + * 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, + NULL /* prim_print */ , +}; + +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/external/boringssl/crypto/asn1/x_long.c b/external/boringssl/crypto/asn1/x_long.c new file mode 100644 index 0000000000..bc4d27518f --- /dev/null +++ b/external/boringssl/crypto/asn1/x_long.c @@ -0,0 +1,197 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include + +/* + * 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(<mp, 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, 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, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + memcpy(cp, <mp, 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/external/boringssl/crypto/base64/CMakeLists.txt b/external/boringssl/crypto/base64/CMakeLists.txt new file mode 100644 index 0000000000..affcb48265 --- /dev/null +++ b/external/boringssl/crypto/base64/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + base64 + + OBJECT + + base64.c +) + +if(ENABLE_TESTS) +add_executable( + base64_test + + base64_test.cc + + $ +) + +target_link_libraries(base64_test crypto) +add_dependencies(all_tests base64_test) +endif() diff --git a/external/boringssl/crypto/base64/base64.c b/external/boringssl/crypto/base64/base64.c new file mode 100644 index 0000000000..0763a3e402 --- /dev/null +++ b/external/boringssl/crypto/base64/base64.c @@ -0,0 +1,438 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include + + +/* Encoding. */ + +static const unsigned char data_bin2ascii[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f]) + +OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0, + data_length_must_be_multiple_of_base64_chunk_size); + +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; +} + +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { + memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); +} + +void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, + const uint8_t *in, size_t in_len) { + size_t total = 0; + + *out_len = 0; + if (in_len == 0) { + return; + } + + assert(ctx->data_used < sizeof(ctx->data)); + + if (sizeof(ctx->data) - ctx->data_used > in_len) { + memcpy(&ctx->data[ctx->data_used], in, in_len); + ctx->data_used += in_len; + return; + } + + if (ctx->data_used != 0) { + const size_t todo = sizeof(ctx->data) - ctx->data_used; + memcpy(&ctx->data[ctx->data_used], in, todo); + in += todo; + in_len -= todo; + + size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data)); + ctx->data_used = 0; + + out += encoded; + *(out++) = '\n'; + *out = '\0'; + + total = encoded + 1; + } + + while (in_len >= sizeof(ctx->data)) { + size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data)); + in += sizeof(ctx->data); + in_len -= sizeof(ctx->data); + + out += encoded; + *(out++) = '\n'; + *out = '\0'; + + if (total + encoded + 1 < total) { + *out_len = 0; + return; + } + + total += encoded + 1; + } + + if (in_len != 0) { + memcpy(ctx->data, in, in_len); + } + + ctx->data_used = in_len; + + if (total > INT_MAX) { + /* We cannot signal an error, but we can at least avoid making *out_len + * negative. */ + total = 0; + } + *out_len = total; +} + +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { + if (ctx->data_used == 0) { + *out_len = 0; + return; + } + + size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used); + out[encoded++] = '\n'; + out[encoded] = '\0'; + ctx->data_used = 0; + *out_len = encoded; +} + +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; +} + + +/* Decoding. */ + +int EVP_DecodedLength(size_t *out_len, size_t len) { + if (len % 4 != 0) { + return 0; + } + + *out_len = (len / 4) * 3; + return 1; +} + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { + memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); +} + +/* kBase64ASCIIToBinData maps characters (c < 128) to their base64 value, or + * else 0xff if they are invalid. As a special case, the padding character + * ('=') is mapped to zero. */ +static const uint8_t kBase64ASCIIToBinData[128] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, + 0xff, 0xff, 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, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static uint8_t base64_ascii_to_bin(uint8_t a) { + if (a >= 128) { + return 0xFF; + } + + return kBase64ASCIIToBinData[a]; +} + +/* base64_decode_quad decodes a single “quad†(i.e. four characters) of base64 + * data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the + * number of bytes written, which will be less than three if the quad ended + * with padding. It returns one on success or zero on error. */ +static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes, + const uint8_t *in) { + const uint8_t a = base64_ascii_to_bin(in[0]); + const uint8_t b = base64_ascii_to_bin(in[1]); + const uint8_t c = base64_ascii_to_bin(in[2]); + const uint8_t d = base64_ascii_to_bin(in[3]); + if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) { + return 0; + } + + const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 | + ((uint32_t)c) << 6 | (uint32_t)d; + + const unsigned padding_pattern = (in[0] == '=') << 3 | + (in[1] == '=') << 2 | + (in[2] == '=') << 1 | + (in[3] == '='); + + switch (padding_pattern) { + case 0: + /* The common case of no padding. */ + *out_num_bytes = 3; + out[0] = v >> 16; + out[1] = v >> 8; + out[2] = v; + break; + + case 1: /* xxx= */ + *out_num_bytes = 2; + out[0] = v >> 16; + out[1] = v >> 8; + break; + + case 3: /* xx== */ + *out_num_bytes = 1; + out[0] = v >> 16; + break; + + default: + return 0; + } + + return 1; +} + +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, + const uint8_t *in, size_t in_len) { + *out_len = 0; + + if (ctx->error_encountered) { + return -1; + } + + size_t bytes_out = 0, i; + for (i = 0; i < in_len; i++) { + const char c = in[i]; + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': + continue; + } + + if (base64_ascii_to_bin(c) == 0xff || ctx->eof_seen) { + ctx->error_encountered = 1; + return -1; + } + + ctx->data[ctx->data_used++] = c; + if (ctx->data_used == 4) { + size_t num_bytes_resulting; + if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) { + ctx->error_encountered = 1; + return -1; + } + + ctx->data_used = 0; + bytes_out += num_bytes_resulting; + out += num_bytes_resulting; + + if (num_bytes_resulting < 3) { + ctx->eof_seen = 1; + } + } + } + + if (bytes_out > INT_MAX) { + ctx->error_encountered = 1; + *out_len = 0; + return -1; + } + *out_len = bytes_out; + + if (ctx->eof_seen) { + return 0; + } + + return 1; +} + +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { + *out_len = 0; + if (ctx->error_encountered || ctx->data_used != 0) { + return -1; + } + + return 1; +} + +int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, + const uint8_t *in, size_t in_len) { + *out_len = 0; + + if (in_len % 4 != 0) { + return 0; + } + + size_t max_len; + if (!EVP_DecodedLength(&max_len, in_len) || + max_out < max_len) { + return 0; + } + + size_t i, bytes_out = 0; + for (i = 0; i < in_len; i += 4) { + size_t num_bytes_resulting; + + if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) { + return 0; + } + + bytes_out += num_bytes_resulting; + out += num_bytes_resulting; + if (num_bytes_resulting != 3 && i != in_len - 4) { + return 0; + } + } + + *out_len = bytes_out; + return 1; +} + +int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { + /* Trim spaces and tabs from the beginning of the input. */ + while (src_len > 0) { + if (src[0] != ' ' && src[0] != '\t') { + break; + } + + src++; + src_len--; + } + + /* Trim newlines, spaces and tabs from the end of the line. */ + while (src_len > 0) { + switch (src[src_len-1]) { + case ' ': + case '\t': + case '\r': + case '\n': + src_len--; + continue; + } + + break; + } + + size_t dst_len; + if (!EVP_DecodedLength(&dst_len, src_len) || + dst_len > INT_MAX || + !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; +} diff --git a/external/boringssl/crypto/base64/base64_test.cc b/external/boringssl/crypto/base64/base64_test.cc new file mode 100644 index 0000000000..a608773213 --- /dev/null +++ b/external/boringssl/crypto/base64/base64_test.cc @@ -0,0 +1,393 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + +#include +#include +#include + + +enum encoding_relation { + // canonical indicates that the encoding is the expected encoding of the + // input. + canonical, + // valid indicates that the encoding is /a/ valid encoding of the input, but + // need not be the canonical one. + valid, + // invalid indicates that the encoded data is valid. + invalid, +}; + +struct TestVector { + enum encoding_relation relation; + const char *decoded; + const char *encoded; +}; + +// Test vectors from RFC 4648. +static const TestVector kTestVectors[] = { + {canonical, "", ""}, + {canonical, "f", "Zg==\n"}, + {canonical, "fo", "Zm8=\n"}, + {canonical, "foo", "Zm9v\n"}, + {canonical, "foob", "Zm9vYg==\n"}, + {canonical, "fooba", "Zm9vYmE=\n"}, + {canonical, "foobar", "Zm9vYmFy\n"}, + {valid, "foobar", "Zm9vYmFy\n\n"}, + {valid, "foobar", " Zm9vYmFy\n\n"}, + {valid, "foobar", " Z m 9 v Y m F y\n\n"}, + {invalid, "", "Zm9vYmFy=\n"}, + {invalid, "", "Zm9vYmFy==\n"}, + {invalid, "", "Zm9vYmFy===\n"}, + {invalid, "", "Z"}, + {invalid, "", "Z\n"}, + {invalid, "", "ab!c"}, + {invalid, "", "ab=c"}, + {invalid, "", "abc"}, + + {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n"}, + {invalid, "", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n==\n"}, + {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh" + "4eHh4eHh4\n"}, + {canonical, + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh" + "4eHh4eHh4eHh4eA==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh" + "4eHh4eHh4eHh4eA==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e" + "Hh4eHh4eHh4eA==\n"}, + {invalid, "", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==" + "\neHh4eHh4eHh4eHh4eHh4eHh4\n"}, + + // A '-' has traditionally been treated as the end of the data by OpenSSL + // and anything following would be ignored. BoringSSL does not accept this + // non-standard extension. + {invalid, "", "Zm9vYmFy-anythinggoes"}, + {invalid, "", "Zm9vYmFy\n-anythinggoes"}, + + // CVE-2015-0292 + {invalid, "", + "ZW5jb2RlIG1lCg===========================================================" + "=======\n"}, +}; + +static const size_t kNumTests = sizeof(kTestVectors) / sizeof(kTestVectors[0]); + +// RemoveNewlines returns a copy of |in| with all '\n' characters removed. +static std::string RemoveNewlines(const char *in) { + std::string ret; + const size_t in_len = strlen(in); + + size_t i; + for (i = 0; i < in_len; i++) { + if (in[i] != '\n') { + ret.push_back(in[i]); + } + } + + return ret; +} + +static bool TestEncodeBlock() { + for (unsigned i = 0; i < kNumTests; i++) { + const TestVector *t = &kTestVectors[i]; + if (t->relation != canonical) { + continue; + } + + const size_t decoded_len = strlen(t->decoded); + size_t max_encoded_len; + if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) { + fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i); + return false; + } + + std::vector out_vec(max_encoded_len); + uint8_t *out = out_vec.data(); + size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len); + + std::string encoded(RemoveNewlines(t->encoded)); + if (len != encoded.size() || + memcmp(out, encoded.data(), len) != 0) { + fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n", + t->decoded, (int)len, (const char*)out, encoded.c_str()); + return false; + } + } + + return true; +} + +static bool TestDecodeBase64() { + size_t len; + + for (unsigned i = 0; i < kNumTests; i++) { + const TestVector *t = &kTestVectors[i]; + + if (t->relation == valid) { + // The non-canonical encodings will generally have odd whitespace etc + // that |EVP_DecodeBase64| will reject. + continue; + } + + const std::string encoded(RemoveNewlines(t->encoded)); + std::vector out_vec(encoded.size()); + uint8_t *out = out_vec.data(); + + int ok = EVP_DecodeBase64(out, &len, out_vec.size(), + (const uint8_t *)encoded.data(), encoded.size()); + + if (t->relation == invalid) { + if (ok) { + fprintf(stderr, "decode(\"%s\") didn't fail but should have\n", + encoded.c_str()); + return false; + } + } else if (t->relation == canonical) { + if (!ok) { + fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str()); + return false; + } + + if (len != strlen(t->decoded) || + memcmp(out, t->decoded, len) != 0) { + fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n", + encoded.c_str(), (int)len, (const char*)out, t->decoded); + return false; + } + } + } + + return true; +} + +static bool TestDecodeBlock() { + for (unsigned i = 0; i < kNumTests; i++) { + const TestVector *t = &kTestVectors[i]; + if (t->relation != canonical) { + continue; + } + + std::string encoded(RemoveNewlines(t->encoded)); + + std::vector out_vec(encoded.size()); + uint8_t *out = out_vec.data(); + + // Test that the padding behavior of the deprecated API is preserved. + int ret = + EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size()); + if (ret < 0) { + fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded); + return false; + } + if (ret % 3 != 0) { + fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n"); + return false; + } + size_t expected_len = strlen(t->decoded); + if (expected_len % 3 != 0) { + ret -= 3 - (expected_len % 3); + } + if (static_cast(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 false; + } + } + + return true; +} + +static bool TestEncodeDecode() { + for (unsigned test_num = 0; test_num < kNumTests; test_num++) { + const TestVector *t = &kTestVectors[test_num]; + + EVP_ENCODE_CTX ctx; + const size_t decoded_len = strlen(t->decoded); + + if (t->relation == canonical) { + size_t max_encoded_len; + if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) { + fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num); + return false; + } + + // EVP_EncodeUpdate will output new lines every 64 bytes of output so we + // need slightly more than |EVP_EncodedLength| returns. */ + max_encoded_len += (max_encoded_len + 63) >> 6; + std::vector out_vec(max_encoded_len); + uint8_t *out = out_vec.data(); + + EVP_EncodeInit(&ctx); + + int out_len; + EVP_EncodeUpdate(&ctx, out, &out_len, + reinterpret_cast(t->decoded), + decoded_len); + size_t total = out_len; + + EVP_EncodeFinal(&ctx, out + total, &out_len); + total += out_len; + + if (total != strlen(t->encoded) || memcmp(out, t->encoded, total) != 0) { + fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n", + test_num, out, static_cast(total)); + return false; + } + } + + std::vector out_vec(strlen(t->encoded)); + uint8_t *out = out_vec.data(); + + EVP_DecodeInit(&ctx); + int out_len; + size_t total = 0; + int ret = EVP_DecodeUpdate(&ctx, out, &out_len, + reinterpret_cast(t->encoded), + strlen(t->encoded)); + if (ret != -1) { + total = out_len; + ret = EVP_DecodeFinal(&ctx, out + total, &out_len); + total += out_len; + } + + switch (t->relation) { + case canonical: + case valid: + if (ret == -1) { + fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num); + return false; + } + if (total != decoded_len || memcmp(out, t->decoded, decoded_len)) { + fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n", + test_num); + return false; + } + break; + + case invalid: + if (ret != -1) { + fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num); + return false; + } + break; + } + } + + return true; +} + +static bool TestDecodeUpdateStreaming() { + for (unsigned test_num = 0; test_num < kNumTests; test_num++) { + const TestVector *t = &kTestVectors[test_num]; + if (t->relation == invalid) { + continue; + } + + const size_t encoded_len = strlen(t->encoded); + + std::vector out(encoded_len); + + for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) { + size_t out_len = 0; + EVP_ENCODE_CTX ctx; + EVP_DecodeInit(&ctx); + + for (size_t i = 0; i < encoded_len;) { + size_t todo = encoded_len - i; + if (todo > chunk_size) { + todo = chunk_size; + } + + int bytes_written; + int ret = EVP_DecodeUpdate( + &ctx, out.data() + out_len, &bytes_written, + reinterpret_cast(t->encoded + i), todo); + i += todo; + + switch (ret) { + case -1: + fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num); + return 0; + case 0: + out_len += bytes_written; + if (i == encoded_len || + (i + 1 == encoded_len && t->encoded[i] == '\n') || + /* If there was an '-' in the input (which means “EOFâ€) then + * this loop will continue to test that |EVP_DecodeUpdate| will + * ignore the remainder of the input. */ + strchr(t->encoded, '-') != nullptr) { + break; + } + + fprintf(stderr, + "#%u: EVP_DecodeUpdate returned zero before end of " + "encoded data\n", + test_num); + return 0; + default: + out_len += bytes_written; + } + } + + int bytes_written; + int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written); + if (ret == -1) { + fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num); + return 0; + } + out_len += bytes_written; + + if (out_len != strlen(t->decoded) || + memcmp(out.data(), t->decoded, out_len) != 0) { + fprintf(stderr, "#%u: incorrect output\n", test_num); + return 0; + } + } + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestEncodeBlock() || + !TestDecodeBase64() || + !TestDecodeBlock() || + !TestDecodeUpdateStreaming() || + !TestEncodeDecode()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/bio/CMakeLists.txt b/external/boringssl/crypto/bio/CMakeLists.txt new file mode 100644 index 0000000000..c5766dddc3 --- /dev/null +++ b/external/boringssl/crypto/bio/CMakeLists.txt @@ -0,0 +1,35 @@ +include_directories(../../include) + +add_library( + bio + + OBJECT + + bio.c + bio_mem.c + buffer.c + connect.c + fd.c + file.c + hexdump.c + pair.c + printf.c + socket.c + socket_helper.c +) + +if(ENABLE_TESTS) +add_executable( + bio_test + + bio_test.cc + + $ +) + +target_link_libraries(bio_test crypto) +if (WIN32) + target_link_libraries(bio_test ws2_32) +endif() +add_dependencies(all_tests bio_test) +endif() diff --git a/external/boringssl/crypto/bio/bio.c b/external/boringssl/crypto/bio/bio.c new file mode 100644 index 0000000000..7a1a9e3b9e --- /dev/null +++ b/external/boringssl/crypto/bio/bio.c @@ -0,0 +1,608 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "../internal.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 (method->create != NULL && !method->create(bio)) { + return 0; + } + + return 1; +} + +BIO *BIO_new(const BIO_METHOD *method) { + BIO *ret = OPENSSL_malloc(sizeof(BIO)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BIO, 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) { + if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) { + 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); + + if (bio->method != NULL && bio->method->destroy != NULL) { + bio->method->destroy(bio); + } + + OPENSSL_free(bio); + } + return 1; +} + +BIO *BIO_up_ref(BIO *bio) { + CRYPTO_refcount_inc(&bio->references); + return bio; +} + +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_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_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_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_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; + return bio; +} + +BIO *BIO_pop(BIO *bio) { + BIO *ret; + + if (bio == NULL) { + return NULL; + } + ret = bio->next_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; +} + +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); +} + +void ERR_print_errors(BIO *bio) { + BIO_print_errors(bio); +} + +/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On + * success, |*out| is set to an allocated buffer (which should be freed with + * |OPENSSL_free|), |*out_len| is set to its length and one is returned. The + * buffer will contain |prefix| followed by the contents of |bio|. On failure, + * zero is returned. + * + * The function will fail if the size of the output would equal or exceed + * |max_len|. */ +static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len, + const uint8_t *prefix, size_t prefix_len, + size_t max_len) { + static const size_t kChunkSize = 4096; + + size_t len = prefix_len + kChunkSize; + if (len > max_len) { + len = max_len; + } + if (len < prefix_len) { + return 0; + } + *out = OPENSSL_malloc(len); + if (*out == NULL) { + return 0; + } + memcpy(*out, prefix, prefix_len); + size_t done = prefix_len; + + for (;;) { + if (done == len) { + OPENSSL_free(*out); + return 0; + } + const size_t todo = len - done; + assert(todo < INT_MAX); + const int n = BIO_read(bio, *out + done, todo); + if (n == 0) { + *out_len = done; + return 1; + } else if (n == -1) { + OPENSSL_free(*out); + return 0; + } + + done += n; + if (len < max_len && len - done < kChunkSize / 2) { + len += kChunkSize; + if (len < kChunkSize || len > max_len) { + len = max_len; + } + uint8_t *new_buf = OPENSSL_realloc(*out, len); + if (new_buf == NULL) { + OPENSSL_free(*out); + return 0; + } + *out = new_buf; + } + } +} + +int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) { + uint8_t header[6]; + + static const size_t kInitialHeaderLen = 2; + if (BIO_read(bio, header, kInitialHeaderLen) != (int) kInitialHeaderLen) { + return 0; + } + + const uint8_t tag = header[0]; + const uint8_t length_byte = header[1]; + + if ((tag & 0x1f) == 0x1f) { + /* Long form tags are not supported. */ + return 0; + } + + size_t len, header_len; + if ((length_byte & 0x80) == 0) { + /* Short form length. */ + len = length_byte; + header_len = kInitialHeaderLen; + } else { + const size_t num_bytes = length_byte & 0x7f; + + if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) { + /* indefinite length. */ + return bio_read_all(bio, out, out_len, header, kInitialHeaderLen, + max_len); + } + + if (num_bytes == 0 || num_bytes > 4) { + return 0; + } + + if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) != + (int)num_bytes) { + return 0; + } + header_len = kInitialHeaderLen + num_bytes; + + uint32_t len32 = 0; + unsigned i; + for (i = 0; i < num_bytes; i++) { + len32 <<= 8; + len32 |= header[kInitialHeaderLen + i]; + } + + 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 + header_len < len || + len + header_len > max_len || + len > INT_MAX) { + return 0; + } + len += header_len; + *out_len = len; + + *out = OPENSSL_malloc(len); + if (*out == NULL) { + return 0; + } + memcpy(*out, header, header_len); + if (BIO_read(bio, (*out) + header_len, len - header_len) != + (int) (len - header_len)) { + OPENSSL_free(*out); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/bio/bio_mem.c b/external/boringssl/crypto/bio/bio_mem.c new file mode 100644 index 0000000000..844fba7e3e --- /dev/null +++ b/external/boringssl/crypto/bio/bio_mem.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.] */ + +#include + +#include +#include + +#include +#include +#include + + +BIO *BIO_new_mem_buf(const 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_R_NULL_PARAMETER); + return NULL; + } + + ret = BIO_new(BIO_s_mem()); + if (ret == NULL) { + return NULL; + } + + b = (BUF_MEM *)ret->ptr; + /* BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to. */ + b->data = (void *)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, 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) != ((size_t) 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/external/boringssl/crypto/bio/bio_test.cc b/external/boringssl/crypto/bio/bio_test.cc new file mode 100644 index 0000000000..f2eb20bab1 --- /dev/null +++ b/external/boringssl/crypto/bio/bio_test.cc @@ -0,0 +1,440 @@ +/* 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 + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#include +#include +#include +#include +#else +#include +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include +#include +#include + +#include + +#include "../test/scoped_types.h" + + +#if !defined(OPENSSL_WINDOWS) +static int closesocket(int sock) { + return close(sock); +} + +static void PrintSocketError(const char *func) { + perror(func); +} +#else +static void PrintSocketError(const char *func) { + fprintf(stderr, "%s: %d\n", func, WSAGetLastError()); +} +#endif + +class ScopedSocket { + public: + ScopedSocket(int sock) : sock_(sock) {} + ~ScopedSocket() { + closesocket(sock_); + } + + private: + const int sock_; +}; + +static bool TestSocketConnect() { + static const char kTestMessage[] = "test"; + + int listening_sock = socket(AF_INET, SOCK_STREAM, 0); + if (listening_sock == -1) { + PrintSocketError("socket"); + return false; + } + ScopedSocket listening_sock_closer(listening_sock); + + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) { + PrintSocketError("inet_pton"); + return false; + } + if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) { + PrintSocketError("bind"); + return false; + } + if (listen(listening_sock, 1)) { + PrintSocketError("listen"); + return false; + } + socklen_t sockaddr_len = sizeof(sin); + if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) || + sockaddr_len != sizeof(sin)) { + PrintSocketError("getsockname"); + return false; + } + + char hostname[80]; + BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1", + ntohs(sin.sin_port)); + ScopedBIO bio(BIO_new_connect(hostname)); + if (!bio) { + fprintf(stderr, "BIO_new_connect failed.\n"); + return false; + } + + if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) != + sizeof(kTestMessage)) { + fprintf(stderr, "BIO_write failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len); + if (sock == -1) { + PrintSocketError("accept"); + return false; + } + ScopedSocket sock_closer(sock); + + char buf[5]; + if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) { + PrintSocketError("read"); + return false; + } + if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) { + return false; + } + + return true; +} + + +// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make +// testing easier. +static size_t BioReadZeroCopyWrapper(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 = std::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; +} + +// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make +// testing easier. +static size_t BioWriteZeroCopyWrapper(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 = std::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 bool TestZeroCopyBioPairs() { + // Test read and write, especially triggering the ring buffer wrap-around. + uint8_t bio1_application_send_buffer[1024]; + uint8_t bio2_application_recv_buffer[1024]; + + 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 (size_t 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 (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) { + for (size_t j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]); + j++) { + size_t total_write = 0; + size_t total_read = 0; + + BIO *bio1, *bio2; + if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) { + return false; + } + ScopedBIO bio1_scoper(bio1); + ScopedBIO bio2_scoper(bio2); + + total_write += BioWriteZeroCopyWrapper( + bio1, bio1_application_send_buffer, kLengths[i]); + + // This tests interleaved read/write calls. Do a read between zero copy + // write calls. + uint8_t *write_buf; + size_t write_buf_offset; + size_t available_bytes; + if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset, + &available_bytes)) { + return false; + } + + // 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 = std::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 += BioWriteZeroCopyWrapper( + bio1, bio1_application_send_buffer + total_write, + kPartialLengths[j] - interleaved_write_len); + + // Drain the rest. + size_t bytes_left = BIO_pending(bio2); + total_read += BioReadZeroCopyWrapper( + bio2, bio2_application_recv_buffer + total_read, bytes_left); + + if (total_read != total_write) { + fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i, + (unsigned)j); + return false; + } + if (total_read > kLengths[i] + kPartialLengths[j]) { + fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i, + (unsigned)j); + return false; + } + 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 false; + } + } + } + + return true; +} + +static bool TestPrintf() { + // 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 }; + + ScopedBIO bio(BIO_new(BIO_s_mem())); + if (!bio) { + fprintf(stderr, "BIO_new failed\n"); + return false; + } + + for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) { + char string[1024]; + if (kLengths[i] >= sizeof(string)) { + fprintf(stderr, "Bad test string length\n"); + return false; + } + memset(string, 'a', sizeof(string)); + string[kLengths[i]] = '\0'; + + int ret = BIO_printf(bio.get(), "test %s", string); + if (ret < 0 || static_cast(ret) != 5 + kLengths[i]) { + fprintf(stderr, "BIO_printf failed: %d\n", ret); + return false; + } + const uint8_t *contents; + size_t len; + if (!BIO_mem_contents(bio.get(), &contents, &len)) { + fprintf(stderr, "BIO_mem_contents failed\n"); + return false; + } + 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 false; + } + + if (!BIO_reset(bio.get())) { + fprintf(stderr, "BIO_reset failed\n"); + return false; + } + } + + return true; +} + +static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len, + size_t expected_len, size_t max_len) { + ScopedBIO bio(BIO_new_mem_buf(data, data_len)); + + uint8_t *out; + size_t out_len; + int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len); + if (!ok) { + out = nullptr; + } + ScopedOpenSSLBytes out_storage(out); + + if (should_succeed != (ok == 1)) { + return false; + } + + if (should_succeed && + (out_len != expected_len || memcmp(data, out, expected_len) != 0)) { + return false; + } + + return true; +} + +static bool TestASN1() { + static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0}; + static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */ + static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */ + static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */ + + if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) || + !ReadASN1(false, kData2, sizeof(kData2), 0, 100) || + !ReadASN1(false, kData3, sizeof(kData3), 0, 100) || + !ReadASN1(false, kData4, sizeof(kData4), 0, 100)) { + return false; + } + + static const size_t kLargePayloadLen = 8000; + static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8, + kLargePayloadLen & 0xff}; + ScopedOpenSSLBytes large(reinterpret_cast( + OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen))); + if (!large) { + return false; + } + memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen); + memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix)); + + if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen * 2)) { + fprintf(stderr, "Large payload test failed.\n"); + return false; + } + + if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen - 1)) { + fprintf(stderr, "max_len test failed.\n"); + return false; + } + + static const uint8_t kIndefPrefix[] = {0x30, 0x80}; + memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix)); + if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen*2)) { + fprintf(stderr, "indefinite length test failed.\n"); + return false; + } + + if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen-1)) { + fprintf(stderr, "indefinite length, max_len test failed.\n"); + return false; + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + +#if defined(OPENSSL_WINDOWS) + // Initialize Winsock. + WORD wsa_version = MAKEWORD(2, 2); + WSADATA wsa_data; + int 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 (!TestSocketConnect() || + !TestPrintf() || + !TestZeroCopyBioPairs() || + !TestASN1()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/bio/buffer.c b/external/boringssl/crypto/bio/buffer.c new file mode 100644 index 0000000000..15574510c1 --- /dev/null +++ b/external/boringssl/crypto/bio/buffer.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 + +#include + +#include +#include +#include + + +#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 = 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 || bio->ptr == NULL) { + return 0; + } + + ctx = (BIO_F_BUFFER_CTX *)bio->ptr; + OPENSSL_free(ctx->ibuf); + 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 = OPENSSL_malloc(ibs); + if (p1 == NULL) { + goto malloc_error; + } + } + if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) { + p2 = 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, 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/external/boringssl/crypto/bio/connect.c b/external/boringssl/crypto/bio/connect.c new file mode 100644 index 0000000000..7e544474dd --- /dev/null +++ b/external/boringssl/crypto/bio/connect.c @@ -0,0 +1,553 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#include +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include +#include + +#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; + + 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 + +/* split_host_and_port sets |*out_host| and |*out_port| to the host and port + * parsed from |name|. It returns one on success or zero on error. Even when + * successful, |*out_port| may be NULL on return if no port was specified. */ +static int split_host_and_port(char **out_host, char **out_port, const char *name) { + const char *host, *port = NULL; + size_t host_len = 0; + + *out_host = NULL; + *out_port = NULL; + + if (name[0] == '[') { /* bracketed IPv6 address */ + const char *close = strchr(name, ']'); + if (close == NULL) { + return 0; + } + host = name + 1; + host_len = close - host; + if (close[1] == ':') { /* [IP]:port */ + port = close + 2; + } else if (close[1] != 0) { + return 0; + } + } else { + const char *colon = strchr(name, ':'); + if (colon == NULL || strchr(colon + 1, ':') != NULL) { /* IPv6 address */ + host = name; + host_len = strlen(name); + } else { /* host:port */ + host = name; + host_len = colon - name; + port = colon + 1; + } + } + + *out_host = BUF_strndup(host, host_len); + if (*out_host == NULL) { + return 0; + } + if (port == NULL) { + *out_port = NULL; + return 1; + } + *out_port = OPENSSL_strdup(port); + if (*out_port == NULL) { + OPENSSL_free(*out_host); + *out_host = NULL; + return 0; + } + return 1; +} + +static int conn_state(BIO *bio, BIO_CONNECT *c) { + int ret = -1, i; + 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: + /* If there's a hostname and a port, assume that both are + * exactly what they say. If there is only a hostname, try + * (just once) to split it into a hostname and port. */ + + if (c->param_hostname == NULL) { + OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED); + goto exit_loop; + } + + if (c->param_port == NULL) { + char *host, *port; + if (!split_host_and_port(&host, &port, c->param_hostname) || + port == NULL) { + OPENSSL_free(host); + OPENSSL_free(port); + OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED); + ERR_add_error_data(2, "host=", c->param_hostname); + goto exit_loop; + } + + OPENSSL_free(c->param_port); + c->param_port = port; + OPENSSL_free(c->param_hostname); + c->param_hostname = host; + } + + 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, BIO_R_UNABLE_TO_CREATE_SOCKET); + ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); + goto exit_loop; + } + + if (c->nbio) { + if (!bio_socket_nbio(bio->num, 1)) { + OPENSSL_PUT_ERROR(BIO, 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(); + OPENSSL_PUT_ERROR(BIO, 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(); + OPENSSL_PUT_ERROR(BIO, 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(); + OPENSSL_PUT_ERROR(BIO, 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; + } + + OPENSSL_free(c->param_hostname); + 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; + 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_SET_CONNECT: + if (ptr != NULL) { + bio->init = 1; + if (num == 0) { + OPENSSL_free(data->param_hostname); + data->param_hostname = BUF_strdup(ptr); + if (data->param_hostname == NULL) { + ret = 0; + } + } else if (num == 1) { + OPENSSL_free(data->param_port); + data->param_port = BUF_strdup(ptr); + if (data->param_port == NULL) { + ret = 0; + } + } 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 = bio->num; + } else { + ret = -1; + } + 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, 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_conn_int_port(BIO *bio, const int *port) { + char buf[DECIMAL_SIZE(int) + 1]; + BIO_snprintf(buf, sizeof(buf), "%d", *port); + return BIO_set_conn_port(bio, buf); +} + +int BIO_set_nbio(BIO *bio, int on) { + return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL); +} + +int BIO_do_connect(BIO *bio) { + return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); +} diff --git a/external/boringssl/crypto/bio/fd.c b/external/boringssl/crypto/bio/fd.c new file mode 100644 index 0000000000..13833df569 --- /dev/null +++ b/external/boringssl/crypto/bio/fd.c @@ -0,0 +1,277 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#else +#include +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include +#include + +#include "internal.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) + #define BORINGSSL_ERRNO (int)GetLastError() + #define BORINGSSL_CLOSE _close + #define BORINGSSL_LSEEK _lseek + #define BORINGSSL_READ _read + #define BORINGSSL_WRITE _write +#else + #define BORINGSSL_ERRNO errno + #define BORINGSSL_CLOSE close + #define BORINGSSL_LSEEK lseek + #define BORINGSSL_READ read + #define BORINGSSL_WRITE write +#endif + +int bio_fd_should_retry(int i) { + if (i == -1) { + return bio_fd_non_fatal_error(BORINGSSL_ERRNO); + } + return 0; +} + +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) { + BORINGSSL_CLOSE(bio->num); + } + bio->init = 0; + } + return 1; +} + +static int fd_read(BIO *b, char *out, int outl) { + int ret = 0; + + ret = BORINGSSL_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 = BORINGSSL_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)BORINGSSL_LSEEK(b->num, num, SEEK_SET); + } + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret = 0; + if (b->init) { + ret = (long)BORINGSSL_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 b->num; + } else { + ret = -1; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_FLUSH: + 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/external/boringssl/crypto/bio/file.c b/external/boringssl/crypto/bio/file.c new file mode 100644 index 0000000000..b903bc28b9 --- /dev/null +++ b/external/boringssl/crypto/bio/file.c @@ -0,0 +1,313 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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 + +#include +#include +#include + +#include +#include +#include + + +#define BIO_FP_READ 0x02 +#define BIO_FP_WRITE 0x04 +#define BIO_FP_APPEND 0x08 + +BIO *BIO_new_file(const char *filename, const char *mode) { + BIO *ret; + FILE *file; + + file = fopen(filename, mode); + if (file == NULL) { + OPENSSL_PUT_SYSTEM_ERROR(); + + ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); + if (errno == ENOENT) { + OPENSSL_PUT_ERROR(BIO, BIO_R_NO_SUCH_FILE); + } else { + OPENSSL_PUT_ERROR(BIO, 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) { + if (!b->init) { + return 0; + } + + size_t ret = fread(out, 1, outl, (FILE *)b->ptr); + if (ret == 0 && ferror((FILE *)b->ptr)) { + OPENSSL_PUT_SYSTEM_ERROR(); + OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB); + return -1; + } + + /* fread reads at most |outl| bytes, so |ret| fits in an int. */ + return (int)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, BIO_R_BAD_FOPEN_MODE); + ret = 0; + break; + } + fp = fopen(ptr, p); + if (fp == NULL) { + OPENSSL_PUT_SYSTEM_ERROR(); + ERR_add_error_data(5, "fopen('", ptr, "','", p, "')"); + OPENSSL_PUT_ERROR(BIO, 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/external/boringssl/crypto/bio/hexdump.c b/external/boringssl/crypto/bio/hexdump.c new file mode 100644 index 0000000000..17f55183f0 --- /dev/null +++ b/external/boringssl/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 + +#include +#include + + +/* 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/external/boringssl/crypto/bio/internal.h b/external/boringssl/crypto/bio/internal.h new file mode 100644 index 0000000000..4ec77fadb6 --- /dev/null +++ b/external/boringssl/crypto/bio/internal.h @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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 + +#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 +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +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/external/boringssl/crypto/bio/pair.c b/external/boringssl/crypto/bio/pair.c new file mode 100644 index 0000000000..2da2d20337 --- /dev/null +++ b/external/boringssl/crypto/bio/pair.c @@ -0,0 +1,803 @@ +/* ==================================================================== + * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + + +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_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_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->peer) { + OPENSSL_PUT_ERROR(BIO, 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_R_UNSUPPORTED_METHOD); + return 0; + } + + if (peer_b->zero_copy_read_lock) { + OPENSSL_PUT_ERROR(BIO, 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_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->peer) { + OPENSSL_PUT_ERROR(BIO, 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_R_UNSUPPORTED_METHOD); + return 0; + } + + if (!peer_b->zero_copy_read_lock) { + OPENSSL_PUT_ERROR(BIO, 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_R_INVALID_ARGUMENT); + return 0; + } + + assert(peer_b->len >= bytes_read); + peer_b->len -= bytes_read; + 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_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->buf || !b->peer) { + OPENSSL_PUT_ERROR(BIO, 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_R_UNSUPPORTED_METHOD); + return 0; + } + + assert(b->buf != NULL); + + if (b->zero_copy_write_lock) { + OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); + return 0; + } + + b->request = 0; + if (b->closed) { + /* Bio is already closed. */ + OPENSSL_PUT_ERROR(BIO, 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_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->buf || !b->peer) { + OPENSSL_PUT_ERROR(BIO, 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_R_UNSUPPORTED_METHOD); + return 0; + } + + b->request = 0; + if (b->closed) { + /* BIO is already closed. */ + OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); + return 0; + } + + if (!b->zero_copy_write_lock) { + OPENSSL_PUT_ERROR(BIO, 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_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_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_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, 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, 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 */ +}; + +static 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) { + BIO_free(bio1); + bio1 = NULL; + 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/external/boringssl/crypto/bio/printf.c b/external/boringssl/crypto/bio/printf.c new file mode 100644 index 0000000000..3709fcb2b3 --- /dev/null +++ b/external/boringssl/crypto/bio/printf.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.] */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L /* for snprintf, vprintf etc */ +#endif + +#include + +#include +#include +#include + +#include +#include + +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 < 0) { + return -1; + } + + if ((size_t) 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) { + OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); + return -1; + } + 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/external/boringssl/crypto/bio/socket.c b/external/boringssl/crypto/bio/socket.c new file mode 100644 index 0000000000..0520c3e830 --- /dev/null +++ b/external/boringssl/crypto/bio/socket.c @@ -0,0 +1,203 @@ +/* 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 + +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#pragma comment(lib, "Ws2_32.lib") +#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(); +#if defined(OPENSSL_WINDOWS) + ret = recv(b->num, out, outl, 0); +#else + ret = read(b->num, out, outl); +#endif + 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(); +#if defined(OPENSSL_WINDOWS) + ret = send(b->num, in, inl, 0); +#else + ret = write(b->num, in, inl); +#endif + 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/external/boringssl/crypto/bio/socket_helper.c b/external/boringssl/crypto/bio/socket_helper.c new file mode 100644 index 0000000000..950078845a --- /dev/null +++ b/external/boringssl/crypto/bio/socket_helper.c @@ -0,0 +1,113 @@ +/* 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. */ + +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L + +#include +#include + +#include +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_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, 0); + ERR_add_error_data(1, gai_strerror(ret)); + return 0; + } + + ret = 0; + + for (cur = result; cur; cur = cur->ai_next) { + if ((size_t) 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(); + 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/external/boringssl/crypto/bn/CMakeLists.txt b/external/boringssl/crypto/bn/CMakeLists.txt new file mode 100644 index 0000000000..81bca4d2e1 --- /dev/null +++ b/external/boringssl/crypto/bn/CMakeLists.txt @@ -0,0 +1,90 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + BN_ARCH_SOURCES + + 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() + +if (${ARCH} STREQUAL "aarch64") + set( + BN_ARCH_SOURCES + + armv8-mont.${ASM_EXT} + ) +endif() + +add_library( + bn + + OBJECT + + add.c + asm/x86_64-gcc.c + bn.c + bn_asn1.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) +perlasm(armv8-mont.${ASM_EXT} asm/armv8-mont.pl) + +if(ENABLE_TESTS) +add_executable( + bn_test + + bn_test.cc + + $ +) + +target_link_libraries(bn_test crypto) +add_dependencies(all_tests bn_test) +endif() diff --git a/external/boringssl/crypto/bn/add.c b/external/boringssl/crypto/bn/add.c new file mode 100644 index 0000000000..23f9f802ce --- /dev/null +++ b/external/boringssl/crypto/bn/add.c @@ -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.] */ + +#include + +#include + +#include +#include + +#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_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 (dif > 0 && rp != ap) { + memcpy(rp, ap, sizeof(*rp) * dif); + } + + 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/external/boringssl/crypto/bn/asm/armv4-mont.pl b/external/boringssl/crypto/bn/asm/armv4-mont.pl new file mode 100644 index 0000000000..b75111288f --- /dev/null +++ b/external/boringssl/crypto/bn/asm/armv4-mont.pl @@ -0,0 +1,693 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + 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 + +.text +.code 32 + +#if __ARM_MAX_ARCH__>=7 +.align 5 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lbn_mul_mont +#endif + +.global bn_mul_mont +.type bn_mul_mont,%function + +.align 5 +bn_mul_mont: +.Lbn_mul_mont: + ldr ip,[sp,#4] @ load num + stmdb sp!,{r0,r2} @ sp points at argument block +#if __ARM_MAX_ARCH__>=7 + tst ip,#7 + bne .Lialu + adr r0,bn_mul_mont + ldr r2,.LOPENSSL_armcap + ldr r0,[r0,r2] +#ifdef __APPLE__ + ldr r0,[r0] +#endif + tst r0,#ARMV7_NEON @ 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: +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.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_MAX_ARCH__>=7 +.arch armv7-a +.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} + ret @ bx lr +.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon +#endif +___ +} +$code.=<<___; +.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +#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; diff --git a/external/boringssl/crypto/bn/asm/armv8-mont.pl b/external/boringssl/crypto/bn/asm/armv8-mont.pl new file mode 100644 index 0000000000..f04aab16bc --- /dev/null +++ b/external/boringssl/crypto/bn/asm/armv8-mont.pl @@ -0,0 +1,1503 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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 2015 +# +# "Teaser" Montgomery multiplication module for ARMv8. Needs more +# work. While it does improve RSA sign performance by 20-30% (less for +# longer keys) on most processors, for some reason RSA2048 is not +# faster and RSA4096 goes 15-20% slower on Cortex-A57. Multiplication +# instruction issue rate is limited on processor in question, meaning +# that dedicated squaring procedure is a must. Well, actually all +# contemporary AArch64 processors seem to have limited multiplication +# issue rate, i.e. they can't issue multiplication every cycle, which +# explains moderate improvement coefficients in comparison to +# compiler-generated code. Recall that compiler is instructed to use +# umulh and therefore uses same amount of multiplication instructions +# to do the job. Assembly's edge is to minimize number of "collateral" +# instructions and of course instruction scheduling. +# +# April 2015 +# +# Squaring procedure that handles lengths divisible by 8 improves +# RSA/DSA performance by 25-40-60% depending on processor and key +# length. Overall improvement coefficients are always positive in +# comparison to compiler-generated code. On Cortex-A57 improvement +# is still modest on longest key lengths, while others exhibit e.g. +# 50-70% improvement for RSA4096 sign. RSA2048 sign is ~25% faster +# on Cortex-A57 and ~60-100% faster on others. + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +($lo0,$hi0,$aj,$m0,$alo,$ahi, + $lo1,$hi1,$nj,$m1,$nlo,$nhi, + $ovf, $i,$j,$tp,$tj) = map("x$_",6..17,19..24); + +# int bn_mul_mont( +$rp="x0"; # BN_ULONG *rp, +$ap="x1"; # const BN_ULONG *ap, +$bp="x2"; # const BN_ULONG *bp, +$np="x3"; # const BN_ULONG *np, +$n0="x4"; # const BN_ULONG *n0, +$num="x5"; # int num); + +$code.=<<___; +.text + +.globl bn_mul_mont +.type bn_mul_mont,%function +.align 5 +bn_mul_mont: + tst $num,#7 + b.eq __bn_sqr8x_mont + tst $num,#3 + b.eq __bn_mul4x_mont +.Lmul_mont: + stp x29,x30,[sp,#-64]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + + ldr $m0,[$bp],#8 // bp[0] + sub $tp,sp,$num,lsl#3 + ldp $hi0,$aj,[$ap],#16 // ap[0..1] + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + and $tp,$tp,#-16 // ABI says so + ldp $hi1,$nj,[$np],#16 // np[0..1] + + mul $lo0,$hi0,$m0 // ap[0]*bp[0] + sub $j,$num,#16 // j=num-2 + umulh $hi0,$hi0,$m0 + mul $alo,$aj,$m0 // ap[1]*bp[0] + umulh $ahi,$aj,$m0 + + mul $m1,$lo0,$n0 // "tp[0]"*n0 + mov sp,$tp // alloca + + // (*) mul $lo1,$hi1,$m1 // np[0]*m1 + umulh $hi1,$hi1,$m1 + mul $nlo,$nj,$m1 // np[1]*m1 + // (*) adds $lo1,$lo1,$lo0 // discarded + // (*) As for removal of first multiplication and addition + // instructions. The outcome of first addition is + // guaranteed to be zero, which leaves two computationally + // significant outcomes: it either carries or not. Then + // question is when does it carry? Is there alternative + // way to deduce it? If you follow operations, you can + // observe that condition for carry is quite simple: + // $lo0 being non-zero. So that carry can be calculated + // by adding -1 to $lo0. That's what next instruction does. + subs xzr,$lo0,#1 // (*) + umulh $nhi,$nj,$m1 + adc $hi1,$hi1,xzr + cbz $j,.L1st_skip + +.L1st: + ldr $aj,[$ap],#8 + adds $lo0,$alo,$hi0 + sub $j,$j,#8 // j-- + adc $hi0,$ahi,xzr + + ldr $nj,[$np],#8 + adds $lo1,$nlo,$hi1 + mul $alo,$aj,$m0 // ap[j]*bp[0] + adc $hi1,$nhi,xzr + umulh $ahi,$aj,$m0 + + adds $lo1,$lo1,$lo0 + mul $nlo,$nj,$m1 // np[j]*m1 + adc $hi1,$hi1,xzr + umulh $nhi,$nj,$m1 + str $lo1,[$tp],#8 // tp[j-1] + cbnz $j,.L1st + +.L1st_skip: + adds $lo0,$alo,$hi0 + sub $ap,$ap,$num // rewind $ap + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + sub $np,$np,$num // rewind $np + adc $hi1,$nhi,xzr + + adds $lo1,$lo1,$lo0 + sub $i,$num,#8 // i=num-1 + adcs $hi1,$hi1,$hi0 + + adc $ovf,xzr,xzr // upmost overflow bit + stp $lo1,$hi1,[$tp] + +.Louter: + ldr $m0,[$bp],#8 // bp[i] + ldp $hi0,$aj,[$ap],#16 + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + + mul $lo0,$hi0,$m0 // ap[0]*bp[i] + sub $j,$num,#16 // j=num-2 + umulh $hi0,$hi0,$m0 + ldp $hi1,$nj,[$np],#16 + mul $alo,$aj,$m0 // ap[1]*bp[i] + adds $lo0,$lo0,$tj + umulh $ahi,$aj,$m0 + adc $hi0,$hi0,xzr + + mul $m1,$lo0,$n0 + sub $i,$i,#8 // i-- + + // (*) mul $lo1,$hi1,$m1 // np[0]*m1 + umulh $hi1,$hi1,$m1 + mul $nlo,$nj,$m1 // np[1]*m1 + // (*) adds $lo1,$lo1,$lo0 + subs xzr,$lo0,#1 // (*) + umulh $nhi,$nj,$m1 + cbz $j,.Linner_skip + +.Linner: + ldr $aj,[$ap],#8 + adc $hi1,$hi1,xzr + ldr $tj,[$tp],#8 // tp[j] + adds $lo0,$alo,$hi0 + sub $j,$j,#8 // j-- + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + ldr $nj,[$np],#8 + adc $hi1,$nhi,xzr + + mul $alo,$aj,$m0 // ap[j]*bp[i] + adds $lo0,$lo0,$tj + umulh $ahi,$aj,$m0 + adc $hi0,$hi0,xzr + + mul $nlo,$nj,$m1 // np[j]*m1 + adds $lo1,$lo1,$lo0 + umulh $nhi,$nj,$m1 + str $lo1,[$tp,#-16] // tp[j-1] + cbnz $j,.Linner + +.Linner_skip: + ldr $tj,[$tp],#8 // tp[j] + adc $hi1,$hi1,xzr + adds $lo0,$alo,$hi0 + sub $ap,$ap,$num // rewind $ap + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + sub $np,$np,$num // rewind $np + adcs $hi1,$nhi,$ovf + adc $ovf,xzr,xzr + + adds $lo0,$lo0,$tj + adc $hi0,$hi0,xzr + + adds $lo1,$lo1,$lo0 + adcs $hi1,$hi1,$hi0 + adc $ovf,$ovf,xzr // upmost overflow bit + stp $lo1,$hi1,[$tp,#-16] + + cbnz $i,.Louter + + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + ldr $nj,[$np],#8 // np[0] + subs $j,$num,#8 // j=num-1 and clear borrow + mov $ap,$rp +.Lsub: + sbcs $aj,$tj,$nj // tp[j]-np[j] + ldr $tj,[$tp],#8 + sub $j,$j,#8 // j-- + ldr $nj,[$np],#8 + str $aj,[$ap],#8 // rp[j]=tp[j]-np[j] + cbnz $j,.Lsub + + sbcs $aj,$tj,$nj + sbcs $ovf,$ovf,xzr // did it borrow? + str $aj,[$ap],#8 // rp[num-1] + + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + ldr $aj,[$rp],#8 // rp[0] + sub $num,$num,#8 // num-- + nop +.Lcond_copy: + sub $num,$num,#8 // num-- + csel $nj,$tj,$aj,lo // did it borrow? + ldr $tj,[$tp],#8 + ldr $aj,[$rp],#8 + str xzr,[$tp,#-16] // wipe tp + str $nj,[$rp,#-16] + cbnz $num,.Lcond_copy + + csel $nj,$tj,$aj,lo + str xzr,[$tp,#-8] // wipe tp + str $nj,[$rp,#-8] + + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldr x29,[sp],#64 + ret +.size bn_mul_mont,.-bn_mul_mont +___ +{ +######################################################################## +# Following is ARMv8 adaptation of sqrx8x_mont from x86_64-mont5 module. + +my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("x$_",(6..13)); +my ($t0,$t1,$t2,$t3)=map("x$_",(14..17)); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("x$_",(19..26)); +my ($cnt,$carry,$topmost)=("x27","x28","x30"); +my ($tp,$ap_end,$na0)=($bp,$np,$carry); + +$code.=<<___; +.type __bn_sqr8x_mont,%function +.align 5 +__bn_sqr8x_mont: + cmp $ap,$bp + b.ne __bn_mul4x_mont +.Lsqr8x_mont: + 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] + stp $rp,$np,[sp,#96] // offload rp and np + + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + ldp $a4,$a5,[$ap,#8*4] + ldp $a6,$a7,[$ap,#8*6] + + sub $tp,sp,$num,lsl#4 + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + mov sp,$tp // alloca + sub $cnt,$num,#8*8 + b .Lsqr8x_zero_start + +.Lsqr8x_zero: + sub $cnt,$cnt,#8*8 + stp xzr,xzr,[$tp,#8*0] + stp xzr,xzr,[$tp,#8*2] + stp xzr,xzr,[$tp,#8*4] + stp xzr,xzr,[$tp,#8*6] +.Lsqr8x_zero_start: + stp xzr,xzr,[$tp,#8*8] + stp xzr,xzr,[$tp,#8*10] + stp xzr,xzr,[$tp,#8*12] + stp xzr,xzr,[$tp,#8*14] + add $tp,$tp,#8*16 + cbnz $cnt,.Lsqr8x_zero + + add $ap_end,$ap,$num + add $ap,$ap,#8*8 + mov $acc0,xzr + mov $acc1,xzr + mov $acc2,xzr + mov $acc3,xzr + mov $acc4,xzr + mov $acc5,xzr + mov $acc6,xzr + mov $acc7,xzr + mov $tp,sp + str $n0,[x29,#112] // offload n0 + + // Multiply everything but a[i]*a[i] +.align 4 +.Lsqr8x_outer_loop: + // a[1]a[0] (i) + // 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] (ii) + // a[3]a[1] + // a[4]a[1] + // a[5]a[1] + // a[6]a[1] + // a[7]a[1] + // a[3]a[2] (iii) + // a[4]a[2] + // a[5]a[2] + // a[6]a[2] + // a[7]a[2] + // a[4]a[3] (iv) + // a[5]a[3] + // a[6]a[3] + // a[7]a[3] + // a[5]a[4] (v) + // a[6]a[4] + // a[7]a[4] + // a[6]a[5] (vi) + // a[7]a[5] + // a[7]a[6] (vii) + + mul $t0,$a1,$a0 // lo(a[1..7]*a[0]) (i) + mul $t1,$a2,$a0 + mul $t2,$a3,$a0 + mul $t3,$a4,$a0 + adds $acc1,$acc1,$t0 // t[1]+lo(a[1]*a[0]) + mul $t0,$a5,$a0 + adcs $acc2,$acc2,$t1 + mul $t1,$a6,$a0 + adcs $acc3,$acc3,$t2 + mul $t2,$a7,$a0 + adcs $acc4,$acc4,$t3 + umulh $t3,$a1,$a0 // hi(a[1..7]*a[0]) + adcs $acc5,$acc5,$t0 + umulh $t0,$a2,$a0 + adcs $acc6,$acc6,$t1 + umulh $t1,$a3,$a0 + adcs $acc7,$acc7,$t2 + umulh $t2,$a4,$a0 + stp $acc0,$acc1,[$tp],#8*2 // t[0..1] + adc $acc0,xzr,xzr // t[8] + adds $acc2,$acc2,$t3 // t[2]+lo(a[1]*a[0]) + umulh $t3,$a5,$a0 + adcs $acc3,$acc3,$t0 + umulh $t0,$a6,$a0 + adcs $acc4,$acc4,$t1 + umulh $t1,$a7,$a0 + adcs $acc5,$acc5,$t2 + mul $t2,$a2,$a1 // lo(a[2..7]*a[1]) (ii) + adcs $acc6,$acc6,$t3 + mul $t3,$a3,$a1 + adcs $acc7,$acc7,$t0 + mul $t0,$a4,$a1 + adc $acc0,$acc0,$t1 + + mul $t1,$a5,$a1 + adds $acc3,$acc3,$t2 + mul $t2,$a6,$a1 + adcs $acc4,$acc4,$t3 + mul $t3,$a7,$a1 + adcs $acc5,$acc5,$t0 + umulh $t0,$a2,$a1 // hi(a[2..7]*a[1]) + adcs $acc6,$acc6,$t1 + umulh $t1,$a3,$a1 + adcs $acc7,$acc7,$t2 + umulh $t2,$a4,$a1 + adcs $acc0,$acc0,$t3 + umulh $t3,$a5,$a1 + stp $acc2,$acc3,[$tp],#8*2 // t[2..3] + adc $acc1,xzr,xzr // t[9] + adds $acc4,$acc4,$t0 + umulh $t0,$a6,$a1 + adcs $acc5,$acc5,$t1 + umulh $t1,$a7,$a1 + adcs $acc6,$acc6,$t2 + mul $t2,$a3,$a2 // lo(a[3..7]*a[2]) (iii) + adcs $acc7,$acc7,$t3 + mul $t3,$a4,$a2 + adcs $acc0,$acc0,$t0 + mul $t0,$a5,$a2 + adc $acc1,$acc1,$t1 + + mul $t1,$a6,$a2 + adds $acc5,$acc5,$t2 + mul $t2,$a7,$a2 + adcs $acc6,$acc6,$t3 + umulh $t3,$a3,$a2 // hi(a[3..7]*a[2]) + adcs $acc7,$acc7,$t0 + umulh $t0,$a4,$a2 + adcs $acc0,$acc0,$t1 + umulh $t1,$a5,$a2 + adcs $acc1,$acc1,$t2 + umulh $t2,$a6,$a2 + stp $acc4,$acc5,[$tp],#8*2 // t[4..5] + adc $acc2,xzr,xzr // t[10] + adds $acc6,$acc6,$t3 + umulh $t3,$a7,$a2 + adcs $acc7,$acc7,$t0 + mul $t0,$a4,$a3 // lo(a[4..7]*a[3]) (iv) + adcs $acc0,$acc0,$t1 + mul $t1,$a5,$a3 + adcs $acc1,$acc1,$t2 + mul $t2,$a6,$a3 + adc $acc2,$acc2,$t3 + + mul $t3,$a7,$a3 + adds $acc7,$acc7,$t0 + umulh $t0,$a4,$a3 // hi(a[4..7]*a[3]) + adcs $acc0,$acc0,$t1 + umulh $t1,$a5,$a3 + adcs $acc1,$acc1,$t2 + umulh $t2,$a6,$a3 + adcs $acc2,$acc2,$t3 + umulh $t3,$a7,$a3 + stp $acc6,$acc7,[$tp],#8*2 // t[6..7] + adc $acc3,xzr,xzr // t[11] + adds $acc0,$acc0,$t0 + mul $t0,$a5,$a4 // lo(a[5..7]*a[4]) (v) + adcs $acc1,$acc1,$t1 + mul $t1,$a6,$a4 + adcs $acc2,$acc2,$t2 + mul $t2,$a7,$a4 + adc $acc3,$acc3,$t3 + + umulh $t3,$a5,$a4 // hi(a[5..7]*a[4]) + adds $acc1,$acc1,$t0 + umulh $t0,$a6,$a4 + adcs $acc2,$acc2,$t1 + umulh $t1,$a7,$a4 + adcs $acc3,$acc3,$t2 + mul $t2,$a6,$a5 // lo(a[6..7]*a[5]) (vi) + adc $acc4,xzr,xzr // t[12] + adds $acc2,$acc2,$t3 + mul $t3,$a7,$a5 + adcs $acc3,$acc3,$t0 + umulh $t0,$a6,$a5 // hi(a[6..7]*a[5]) + adc $acc4,$acc4,$t1 + + umulh $t1,$a7,$a5 + adds $acc3,$acc3,$t2 + mul $t2,$a7,$a6 // lo(a[7]*a[6]) (vii) + adcs $acc4,$acc4,$t3 + umulh $t3,$a7,$a6 // hi(a[7]*a[6]) + adc $acc5,xzr,xzr // t[13] + adds $acc4,$acc4,$t0 + sub $cnt,$ap_end,$ap // done yet? + adc $acc5,$acc5,$t1 + + adds $acc5,$acc5,$t2 + sub $t0,$ap_end,$num // rewinded ap + adc $acc6,xzr,xzr // t[14] + add $acc6,$acc6,$t3 + + cbz $cnt,.Lsqr8x_outer_break + + mov $n0,$a0 + ldp $a0,$a1,[$tp,#8*0] + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + adds $acc0,$acc0,$a0 + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$ap,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$ap,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$ap,#8*4] + adcs $acc6,$acc6,$a6 + mov $rp,$ap + adcs $acc7,xzr,$a7 + ldp $a6,$a7,[$ap,#8*6] + add $ap,$ap,#8*8 + //adc $carry,xzr,xzr // moved below + mov $cnt,#-8*8 + + // a[8]a[0] + // a[9]a[0] + // a[a]a[0] + // a[b]a[0] + // a[c]a[0] + // a[d]a[0] + // a[e]a[0] + // a[f]a[0] + // a[8]a[1] + // a[f]a[1]........................ + // a[8]a[2] + // a[f]a[2]........................ + // a[8]a[3] + // a[f]a[3]........................ + // a[8]a[4] + // a[f]a[4]........................ + // a[8]a[5] + // a[f]a[5]........................ + // a[8]a[6] + // a[f]a[6]........................ + // a[8]a[7] + // a[f]a[7]........................ +.Lsqr8x_mul: + mul $t0,$a0,$n0 + adc $carry,xzr,xzr // carry bit, modulo-scheduled + mul $t1,$a1,$n0 + add $cnt,$cnt,#8 + mul $t2,$a2,$n0 + mul $t3,$a3,$n0 + adds $acc0,$acc0,$t0 + mul $t0,$a4,$n0 + adcs $acc1,$acc1,$t1 + mul $t1,$a5,$n0 + adcs $acc2,$acc2,$t2 + mul $t2,$a6,$n0 + adcs $acc3,$acc3,$t3 + mul $t3,$a7,$n0 + adcs $acc4,$acc4,$t0 + umulh $t0,$a0,$n0 + adcs $acc5,$acc5,$t1 + umulh $t1,$a1,$n0 + adcs $acc6,$acc6,$t2 + umulh $t2,$a2,$n0 + adcs $acc7,$acc7,$t3 + umulh $t3,$a3,$n0 + adc $carry,$carry,xzr + str $acc0,[$tp],#8 + adds $acc0,$acc1,$t0 + umulh $t0,$a4,$n0 + adcs $acc1,$acc2,$t1 + umulh $t1,$a5,$n0 + adcs $acc2,$acc3,$t2 + umulh $t2,$a6,$n0 + adcs $acc3,$acc4,$t3 + umulh $t3,$a7,$n0 + ldr $n0,[$rp,$cnt] + adcs $acc4,$acc5,$t0 + adcs $acc5,$acc6,$t1 + adcs $acc6,$acc7,$t2 + adcs $acc7,$carry,$t3 + //adc $carry,xzr,xzr // moved above + cbnz $cnt,.Lsqr8x_mul + // note that carry flag is guaranteed + // to be zero at this point + cmp $ap,$ap_end // done yet? + b.eq .Lsqr8x_break + + ldp $a0,$a1,[$tp,#8*0] + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + adds $acc0,$acc0,$a0 + ldr $n0,[$rp,#-8*8] + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$ap,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$ap,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$ap,#8*4] + adcs $acc6,$acc6,$a6 + mov $cnt,#-8*8 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$ap,#8*6] + add $ap,$ap,#8*8 + //adc $carry,xzr,xzr // moved above + b .Lsqr8x_mul + +.align 4 +.Lsqr8x_break: + ldp $a0,$a1,[$rp,#8*0] + add $ap,$rp,#8*8 + ldp $a2,$a3,[$rp,#8*2] + sub $t0,$ap_end,$ap // is it last iteration? + ldp $a4,$a5,[$rp,#8*4] + sub $t1,$tp,$t0 + ldp $a6,$a7,[$rp,#8*6] + cbz $t0,.Lsqr8x_outer_loop + + stp $acc0,$acc1,[$tp,#8*0] + ldp $acc0,$acc1,[$t1,#8*0] + stp $acc2,$acc3,[$tp,#8*2] + ldp $acc2,$acc3,[$t1,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[$t1,#8*4] + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,$t1 + ldp $acc6,$acc7,[$t1,#8*6] + b .Lsqr8x_outer_loop + +.align 4 +.Lsqr8x_outer_break: + // Now multiply above result by 2 and add a[n-1]*a[n-1]|...|a[0]*a[0] + ldp $a1,$a3,[$t0,#8*0] // recall that $t0 is &a[0] + ldp $t1,$t2,[sp,#8*1] + ldp $a5,$a7,[$t0,#8*2] + add $ap,$t0,#8*4 + ldp $t3,$t0,[sp,#8*3] + + stp $acc0,$acc1,[$tp,#8*0] + mul $acc0,$a1,$a1 + stp $acc2,$acc3,[$tp,#8*2] + umulh $a1,$a1,$a1 + stp $acc4,$acc5,[$tp,#8*4] + mul $a2,$a3,$a3 + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,sp + umulh $a3,$a3,$a3 + adds $acc1,$a1,$t1,lsl#1 + extr $t1,$t2,$t1,#63 + sub $cnt,$num,#8*4 + +.Lsqr4x_shift_n_add: + adcs $acc2,$a2,$t1 + extr $t2,$t3,$t2,#63 + sub $cnt,$cnt,#8*4 + adcs $acc3,$a3,$t2 + ldp $t1,$t2,[$tp,#8*5] + mul $a4,$a5,$a5 + ldp $a1,$a3,[$ap],#8*2 + umulh $a5,$a5,$a5 + mul $a6,$a7,$a7 + umulh $a7,$a7,$a7 + extr $t3,$t0,$t3,#63 + stp $acc0,$acc1,[$tp,#8*0] + adcs $acc4,$a4,$t3 + extr $t0,$t1,$t0,#63 + stp $acc2,$acc3,[$tp,#8*2] + adcs $acc5,$a5,$t0 + ldp $t3,$t0,[$tp,#8*7] + extr $t1,$t2,$t1,#63 + adcs $acc6,$a6,$t1 + extr $t2,$t3,$t2,#63 + adcs $acc7,$a7,$t2 + ldp $t1,$t2,[$tp,#8*9] + mul $a0,$a1,$a1 + ldp $a5,$a7,[$ap],#8*2 + umulh $a1,$a1,$a1 + mul $a2,$a3,$a3 + umulh $a3,$a3,$a3 + stp $acc4,$acc5,[$tp,#8*4] + extr $t3,$t0,$t3,#63 + stp $acc6,$acc7,[$tp,#8*6] + add $tp,$tp,#8*8 + adcs $acc0,$a0,$t3 + extr $t0,$t1,$t0,#63 + adcs $acc1,$a1,$t0 + ldp $t3,$t0,[$tp,#8*3] + extr $t1,$t2,$t1,#63 + cbnz $cnt,.Lsqr4x_shift_n_add +___ +my ($np,$np_end)=($ap,$ap_end); +$code.=<<___; + ldp $np,$n0,[x29,#104] // pull np and n0 + + adcs $acc2,$a2,$t1 + extr $t2,$t3,$t2,#63 + adcs $acc3,$a3,$t2 + ldp $t1,$t2,[$tp,#8*5] + mul $a4,$a5,$a5 + umulh $a5,$a5,$a5 + stp $acc0,$acc1,[$tp,#8*0] + mul $a6,$a7,$a7 + umulh $a7,$a7,$a7 + stp $acc2,$acc3,[$tp,#8*2] + extr $t3,$t0,$t3,#63 + adcs $acc4,$a4,$t3 + extr $t0,$t1,$t0,#63 + ldp $acc0,$acc1,[sp,#8*0] + adcs $acc5,$a5,$t0 + extr $t1,$t2,$t1,#63 + ldp $a0,$a1,[$np,#8*0] + adcs $acc6,$a6,$t1 + extr $t2,xzr,$t2,#63 + ldp $a2,$a3,[$np,#8*2] + adc $acc7,$a7,$t2 + ldp $a4,$a5,[$np,#8*4] + + // Reduce by 512 bits per iteration + mul $na0,$n0,$acc0 // t[0]*n0 + ldp $a6,$a7,[$np,#8*6] + add $np_end,$np,$num + ldp $acc2,$acc3,[sp,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[sp,#8*4] + stp $acc6,$acc7,[$tp,#8*6] + ldp $acc6,$acc7,[sp,#8*6] + add $np,$np,#8*8 + mov $topmost,xzr // initial top-most carry + mov $tp,sp + mov $cnt,#8 + +.Lsqr8x_reduction: + // (*) mul $t0,$a0,$na0 // lo(n[0-7])*lo(t[0]*n0) + mul $t1,$a1,$na0 + sub $cnt,$cnt,#1 + mul $t2,$a2,$na0 + str $na0,[$tp],#8 // put aside t[0]*n0 for tail processing + mul $t3,$a3,$na0 + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + mul $t0,$a4,$na0 + adcs $acc0,$acc1,$t1 + mul $t1,$a5,$na0 + adcs $acc1,$acc2,$t2 + mul $t2,$a6,$na0 + adcs $acc2,$acc3,$t3 + mul $t3,$a7,$na0 + adcs $acc3,$acc4,$t0 + umulh $t0,$a0,$na0 // hi(n[0-7])*lo(t[0]*n0) + adcs $acc4,$acc5,$t1 + umulh $t1,$a1,$na0 + adcs $acc5,$acc6,$t2 + umulh $t2,$a2,$na0 + adcs $acc6,$acc7,$t3 + umulh $t3,$a3,$na0 + adc $acc7,xzr,xzr + adds $acc0,$acc0,$t0 + umulh $t0,$a4,$na0 + adcs $acc1,$acc1,$t1 + umulh $t1,$a5,$na0 + adcs $acc2,$acc2,$t2 + umulh $t2,$a6,$na0 + adcs $acc3,$acc3,$t3 + umulh $t3,$a7,$na0 + mul $na0,$n0,$acc0 // next t[0]*n0 + adcs $acc4,$acc4,$t0 + adcs $acc5,$acc5,$t1 + adcs $acc6,$acc6,$t2 + adc $acc7,$acc7,$t3 + cbnz $cnt,.Lsqr8x_reduction + + ldp $t0,$t1,[$tp,#8*0] + ldp $t2,$t3,[$tp,#8*2] + mov $rp,$tp + sub $cnt,$np_end,$np // done yet? + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + ldp $t0,$t1,[$tp,#8*4] + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + ldp $t2,$t3,[$tp,#8*6] + adcs $acc4,$acc4,$t0 + adcs $acc5,$acc5,$t1 + adcs $acc6,$acc6,$t2 + adcs $acc7,$acc7,$t3 + //adc $carry,xzr,xzr // moved below + cbz $cnt,.Lsqr8x8_post_condition + + ldr $n0,[$tp,#-8*8] + ldp $a0,$a1,[$np,#8*0] + ldp $a2,$a3,[$np,#8*2] + ldp $a4,$a5,[$np,#8*4] + mov $cnt,#-8*8 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + +.Lsqr8x_tail: + mul $t0,$a0,$n0 + adc $carry,xzr,xzr // carry bit, modulo-scheduled + mul $t1,$a1,$n0 + add $cnt,$cnt,#8 + mul $t2,$a2,$n0 + mul $t3,$a3,$n0 + adds $acc0,$acc0,$t0 + mul $t0,$a4,$n0 + adcs $acc1,$acc1,$t1 + mul $t1,$a5,$n0 + adcs $acc2,$acc2,$t2 + mul $t2,$a6,$n0 + adcs $acc3,$acc3,$t3 + mul $t3,$a7,$n0 + adcs $acc4,$acc4,$t0 + umulh $t0,$a0,$n0 + adcs $acc5,$acc5,$t1 + umulh $t1,$a1,$n0 + adcs $acc6,$acc6,$t2 + umulh $t2,$a2,$n0 + adcs $acc7,$acc7,$t3 + umulh $t3,$a3,$n0 + adc $carry,$carry,xzr + str $acc0,[$tp],#8 + adds $acc0,$acc1,$t0 + umulh $t0,$a4,$n0 + adcs $acc1,$acc2,$t1 + umulh $t1,$a5,$n0 + adcs $acc2,$acc3,$t2 + umulh $t2,$a6,$n0 + adcs $acc3,$acc4,$t3 + umulh $t3,$a7,$n0 + ldr $n0,[$rp,$cnt] + adcs $acc4,$acc5,$t0 + adcs $acc5,$acc6,$t1 + adcs $acc6,$acc7,$t2 + adcs $acc7,$carry,$t3 + //adc $carry,xzr,xzr // moved above + cbnz $cnt,.Lsqr8x_tail + // note that carry flag is guaranteed + // to be zero at this point + ldp $a0,$a1,[$tp,#8*0] + sub $cnt,$np_end,$np // done yet? + sub $t2,$np_end,$num // rewinded np + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + cbz $cnt,.Lsqr8x_tail_break + + ldr $n0,[$rp,#-8*8] + adds $acc0,$acc0,$a0 + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$np,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$np,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$np,#8*4] + adcs $acc6,$acc6,$a6 + mov $cnt,#-8*8 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + //adc $carry,xzr,xzr // moved above + b .Lsqr8x_tail + +.align 4 +.Lsqr8x_tail_break: + ldr $n0,[x29,#112] // pull n0 + add $cnt,$tp,#8*8 // end of current t[num] window + + subs xzr,$topmost,#1 // "move" top-most carry to carry bit + adcs $t0,$acc0,$a0 + adcs $t1,$acc1,$a1 + ldp $acc0,$acc1,[$rp,#8*0] + adcs $acc2,$acc2,$a2 + ldp $a0,$a1,[$t2,#8*0] // recall that $t2 is &n[0] + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$t2,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$t2,#8*4] + adcs $acc6,$acc6,$a6 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$t2,#8*6] + add $np,$t2,#8*8 + adc $topmost,xzr,xzr // top-most carry + mul $na0,$n0,$acc0 + stp $t0,$t1,[$tp,#8*0] + stp $acc2,$acc3,[$tp,#8*2] + ldp $acc2,$acc3,[$rp,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[$rp,#8*4] + cmp $cnt,x29 // did we hit the bottom? + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,$rp // slide the window + ldp $acc6,$acc7,[$rp,#8*6] + mov $cnt,#8 + b.ne .Lsqr8x_reduction + + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + ldr $rp,[x29,#96] // pull rp + add $tp,$tp,#8*8 + subs $t0,$acc0,$a0 + sbcs $t1,$acc1,$a1 + sub $cnt,$num,#8*8 + mov $ap_end,$rp // $rp copy + +.Lsqr8x_sub: + sbcs $t2,$acc2,$a2 + ldp $a0,$a1,[$np,#8*0] + sbcs $t3,$acc3,$a3 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc4,$a4 + ldp $a2,$a3,[$np,#8*2] + sbcs $t1,$acc5,$a5 + stp $t2,$t3,[$rp,#8*2] + sbcs $t2,$acc6,$a6 + ldp $a4,$a5,[$np,#8*4] + sbcs $t3,$acc7,$a7 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + ldp $acc0,$acc1,[$tp,#8*0] + sub $cnt,$cnt,#8*8 + ldp $acc2,$acc3,[$tp,#8*2] + ldp $acc4,$acc5,[$tp,#8*4] + ldp $acc6,$acc7,[$tp,#8*6] + add $tp,$tp,#8*8 + stp $t0,$t1,[$rp,#8*4] + sbcs $t0,$acc0,$a0 + stp $t2,$t3,[$rp,#8*6] + add $rp,$rp,#8*8 + sbcs $t1,$acc1,$a1 + cbnz $cnt,.Lsqr8x_sub + + sbcs $t2,$acc2,$a2 + mov $tp,sp + add $ap,sp,$num + ldp $a0,$a1,[$ap_end,#8*0] + sbcs $t3,$acc3,$a3 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc4,$a4 + ldp $a2,$a3,[$ap_end,#8*2] + sbcs $t1,$acc5,$a5 + stp $t2,$t3,[$rp,#8*2] + sbcs $t2,$acc6,$a6 + ldp $acc0,$acc1,[$ap,#8*0] + sbcs $t3,$acc7,$a7 + ldp $acc2,$acc3,[$ap,#8*2] + sbcs xzr,$topmost,xzr // did it borrow? + ldr x30,[x29,#8] // pull return address + stp $t0,$t1,[$rp,#8*4] + stp $t2,$t3,[$rp,#8*6] + + sub $cnt,$num,#8*4 +.Lsqr4x_cond_copy: + sub $cnt,$cnt,#8*4 + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + ldp $a0,$a1,[$ap_end,#8*4] + ldp $acc0,$acc1,[$ap,#8*4] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*2] + add $tp,$tp,#8*4 + csel $t3,$acc3,$a3,lo + ldp $a2,$a3,[$ap_end,#8*6] + ldp $acc2,$acc3,[$ap,#8*6] + add $ap,$ap,#8*4 + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + add $ap_end,$ap_end,#8*4 + stp xzr,xzr,[$ap,#8*0] + stp xzr,xzr,[$ap,#8*2] + cbnz $cnt,.Lsqr4x_cond_copy + + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + stp xzr,xzr,[$tp,#8*2] + csel $t2,$acc2,$a2,lo + csel $t3,$acc3,$a3,lo + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + + b .Lsqr8x_done + +.align 4 +.Lsqr8x8_post_condition: + adc $carry,xzr,xzr + ldr x30,[x29,#8] // pull return address + // $acc0-7,$carry hold result, $a0-7 hold modulus + subs $a0,$acc0,$a0 + ldr $ap,[x29,#96] // pull rp + sbcs $a1,$acc1,$a1 + stp xzr,xzr,[sp,#8*0] + sbcs $a2,$acc2,$a2 + stp xzr,xzr,[sp,#8*2] + sbcs $a3,$acc3,$a3 + stp xzr,xzr,[sp,#8*4] + sbcs $a4,$acc4,$a4 + stp xzr,xzr,[sp,#8*6] + sbcs $a5,$acc5,$a5 + stp xzr,xzr,[sp,#8*8] + sbcs $a6,$acc6,$a6 + stp xzr,xzr,[sp,#8*10] + sbcs $a7,$acc7,$a7 + stp xzr,xzr,[sp,#8*12] + sbcs $carry,$carry,xzr // did it borrow? + stp xzr,xzr,[sp,#8*14] + + // $a0-7 hold result-modulus + csel $a0,$acc0,$a0,lo + csel $a1,$acc1,$a1,lo + csel $a2,$acc2,$a2,lo + csel $a3,$acc3,$a3,lo + stp $a0,$a1,[$ap,#8*0] + csel $a4,$acc4,$a4,lo + csel $a5,$acc5,$a5,lo + stp $a2,$a3,[$ap,#8*2] + csel $a6,$acc6,$a6,lo + csel $a7,$acc7,$a7,lo + stp $a4,$a5,[$ap,#8*4] + stp $a6,$a7,[$ap,#8*6] + +.Lsqr8x_done: + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldr x29,[sp],#128 + ret +.size __bn_sqr8x_mont,.-__bn_sqr8x_mont +___ +} + +{ +######################################################################## +# Even though this might look as ARMv8 adaptation of mulx4x_mont from +# x86_64-mont5 module, it's different in sense that it performs +# reduction 256 bits at a time. + +my ($a0,$a1,$a2,$a3, + $t0,$t1,$t2,$t3, + $m0,$m1,$m2,$m3, + $acc0,$acc1,$acc2,$acc3,$acc4, + $bi,$mi,$tp,$ap_end,$cnt) = map("x$_",(6..17,19..28)); +my $bp_end=$rp; +my ($carry,$topmost) = ($rp,"x30"); + +$code.=<<___; +.type __bn_mul4x_mont,%function +.align 5 +__bn_mul4x_mont: + 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 $tp,sp,$num,lsl#3 + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + sub sp,$tp,#8*4 // alloca + + add $t0,$bp,$num + add $ap_end,$ap,$num + stp $rp,$t0,[x29,#96] // offload rp and &b[num] + + ldr $bi,[$bp,#8*0] // b[0] + ldp $a0,$a1,[$ap,#8*0] // a[0..3] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + mov $acc0,xzr + mov $acc1,xzr + mov $acc2,xzr + mov $acc3,xzr + ldp $m0,$m1,[$np,#8*0] // n[0..3] + ldp $m2,$m3,[$np,#8*2] + adds $np,$np,#8*4 // clear carry bit + mov $carry,xzr + mov $cnt,#0 + mov $tp,sp + +.Loop_mul4x_1st_reduction: + mul $t0,$a0,$bi // lo(a[0..3]*b[0]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[0..3]*b[0]) + adcs $acc1,$acc1,$t1 + mul $mi,$acc0,$n0 // t[0]*n0 + adcs $acc2,$acc2,$t2 + umulh $t1,$a1,$bi + adcs $acc3,$acc3,$t3 + umulh $t2,$a2,$bi + adc $acc4,xzr,xzr + umulh $t3,$a3,$bi + ldr $bi,[$bp,$cnt] // next b[i] (or b[0]) + adds $acc1,$acc1,$t0 + // (*) mul $t0,$m0,$mi // lo(n[0..3]*t[0]*n0) + str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0) + adcs $acc0,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc1,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc2,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc3,$acc4,$carry + adc $carry,xzr,xzr + adds $acc0,$acc0,$t0 + sub $t0,$ap_end,$ap + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_1st_reduction + + cbz $t0,.Lmul4x4_post_condition + + ldp $a0,$a1,[$ap,#8*0] // a[4..7] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + ldr $mi,[sp] // a[0]*n0 + ldp $m0,$m1,[$np,#8*0] // n[4..7] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + +.Loop_mul4x_1st_tail: + mul $t0,$a0,$bi // lo(a[4..7]*b[i]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[4..7]*b[i]) + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi + adc $acc4,xzr,xzr + ldr $bi,[$bp,$cnt] // next b[i] (or b[0]) + adds $acc1,$acc1,$t0 + mul $t0,$m0,$mi // lo(n[4..7]*a[0]*n0) + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + adds $acc0,$acc0,$t0 + umulh $t0,$m0,$mi // hi(n[4..7]*a[0]*n0) + adcs $acc1,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc2,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc3,$acc3,$t3 + adcs $acc4,$acc4,$carry + umulh $t3,$m3,$mi + adc $carry,xzr,xzr + ldr $mi,[sp,$cnt] // next t[0]*n0 + str $acc0,[$tp],#8 // result!!! + adds $acc0,$acc1,$t0 + sub $t0,$ap_end,$ap // done yet? + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 + adcs $acc3,$acc4,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_1st_tail + + sub $t1,$ap_end,$num // rewinded $ap + cbz $t0,.Lmul4x_proceed + + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + ldp $m0,$m1,[$np,#8*0] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + b .Loop_mul4x_1st_tail + +.align 5 +.Lmul4x_proceed: + ldr $bi,[$bp,#8*4]! // *++b + adc $topmost,$carry,xzr + ldp $a0,$a1,[$t1,#8*0] // a[0..3] + sub $np,$np,$num // rewind np + ldp $a2,$a3,[$t1,#8*2] + add $ap,$t1,#8*4 + + stp $acc0,$acc1,[$tp,#8*0] // result!!! + ldp $acc0,$acc1,[sp,#8*4] // t[0..3] + stp $acc2,$acc3,[$tp,#8*2] // result!!! + ldp $acc2,$acc3,[sp,#8*6] + + ldp $m0,$m1,[$np,#8*0] // n[0..3] + mov $tp,sp + ldp $m2,$m3,[$np,#8*2] + adds $np,$np,#8*4 // clear carry bit + mov $carry,xzr + +.align 4 +.Loop_mul4x_reduction: + mul $t0,$a0,$bi // lo(a[0..3]*b[4]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[0..3]*b[4]) + adcs $acc1,$acc1,$t1 + mul $mi,$acc0,$n0 // t[0]*n0 + adcs $acc2,$acc2,$t2 + umulh $t1,$a1,$bi + adcs $acc3,$acc3,$t3 + umulh $t2,$a2,$bi + adc $acc4,xzr,xzr + umulh $t3,$a3,$bi + ldr $bi,[$bp,$cnt] // next b[i] + adds $acc1,$acc1,$t0 + // (*) mul $t0,$m0,$mi + str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi // lo(n[0..3]*t[0]*n0 + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0 + adcs $acc0,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc1,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc2,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc3,$acc4,$carry + adc $carry,xzr,xzr + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_reduction + + adc $carry,$carry,xzr + ldp $t0,$t1,[$tp,#8*4] // t[4..7] + ldp $t2,$t3,[$tp,#8*6] + ldp $a0,$a1,[$ap,#8*0] // a[4..7] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + + ldr $mi,[sp] // t[0]*n0 + ldp $m0,$m1,[$np,#8*0] // n[4..7] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + +.align 4 +.Loop_mul4x_tail: + mul $t0,$a0,$bi // lo(a[4..7]*b[4]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[4..7]*b[4]) + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi + adc $acc4,xzr,xzr + ldr $bi,[$bp,$cnt] // next b[i] + adds $acc1,$acc1,$t0 + mul $t0,$m0,$mi // lo(n[4..7]*t[0]*n0) + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + adds $acc0,$acc0,$t0 + umulh $t0,$m0,$mi // hi(n[4..7]*t[0]*n0) + adcs $acc1,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc2,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc3,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc4,$acc4,$carry + ldr $mi,[sp,$cnt] // next a[0]*n0 + adc $carry,xzr,xzr + str $acc0,[$tp],#8 // result!!! + adds $acc0,$acc1,$t0 + sub $t0,$ap_end,$ap // done yet? + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 + adcs $acc3,$acc4,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_tail + + sub $t1,$np,$num // rewinded np? + adc $carry,$carry,xzr + cbz $t0,.Loop_mul4x_break + + ldp $t0,$t1,[$tp,#8*4] + ldp $t2,$t3,[$tp,#8*6] + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + ldp $m0,$m1,[$np,#8*0] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + b .Loop_mul4x_tail + +.align 4 +.Loop_mul4x_break: + ldp $t2,$t3,[x29,#96] // pull rp and &b[num] + adds $acc0,$acc0,$topmost + add $bp,$bp,#8*4 // bp++ + adcs $acc1,$acc1,xzr + sub $ap,$ap,$num // rewind ap + adcs $acc2,$acc2,xzr + stp $acc0,$acc1,[$tp,#8*0] // result!!! + adcs $acc3,$acc3,xzr + ldp $acc0,$acc1,[sp,#8*4] // t[0..3] + adc $topmost,$carry,xzr + stp $acc2,$acc3,[$tp,#8*2] // result!!! + cmp $bp,$t3 // done yet? + ldp $acc2,$acc3,[sp,#8*6] + ldp $m0,$m1,[$t1,#8*0] // n[0..3] + ldp $m2,$m3,[$t1,#8*2] + add $np,$t1,#8*4 + b.eq .Lmul4x_post + + ldr $bi,[$bp] + ldp $a0,$a1,[$ap,#8*0] // a[0..3] + ldp $a2,$a3,[$ap,#8*2] + adds $ap,$ap,#8*4 // clear carry bit + mov $carry,xzr + mov $tp,sp + b .Loop_mul4x_reduction + +.align 4 +.Lmul4x_post: + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + mov $rp,$t2 + mov $ap_end,$t2 // $rp copy + subs $t0,$acc0,$m0 + add $tp,sp,#8*8 + sbcs $t1,$acc1,$m1 + sub $cnt,$num,#8*4 + +.Lmul4x_sub: + sbcs $t2,$acc2,$m2 + ldp $m0,$m1,[$np,#8*0] + sub $cnt,$cnt,#8*4 + ldp $acc0,$acc1,[$tp,#8*0] + sbcs $t3,$acc3,$m3 + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + ldp $acc2,$acc3,[$tp,#8*2] + add $tp,$tp,#8*4 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc0,$m0 + stp $t2,$t3,[$rp,#8*2] + add $rp,$rp,#8*4 + sbcs $t1,$acc1,$m1 + cbnz $cnt,.Lmul4x_sub + + sbcs $t2,$acc2,$m2 + mov $tp,sp + add $ap,sp,#8*4 + ldp $a0,$a1,[$ap_end,#8*0] + sbcs $t3,$acc3,$m3 + stp $t0,$t1,[$rp,#8*0] + ldp $a2,$a3,[$ap_end,#8*2] + stp $t2,$t3,[$rp,#8*2] + ldp $acc0,$acc1,[$ap,#8*0] + ldp $acc2,$acc3,[$ap,#8*2] + sbcs xzr,$topmost,xzr // did it borrow? + ldr x30,[x29,#8] // pull return address + + sub $cnt,$num,#8*4 +.Lmul4x_cond_copy: + sub $cnt,$cnt,#8*4 + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + ldp $a0,$a1,[$ap_end,#8*4] + ldp $acc0,$acc1,[$ap,#8*4] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*2] + add $tp,$tp,#8*4 + csel $t3,$acc3,$a3,lo + ldp $a2,$a3,[$ap_end,#8*6] + ldp $acc2,$acc3,[$ap,#8*6] + add $ap,$ap,#8*4 + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + add $ap_end,$ap_end,#8*4 + cbnz $cnt,.Lmul4x_cond_copy + + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + stp xzr,xzr,[$tp,#8*2] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*3] + csel $t3,$acc3,$a3,lo + stp xzr,xzr,[$tp,#8*4] + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + + b .Lmul4x_done + +.align 4 +.Lmul4x4_post_condition: + adc $carry,$carry,xzr + ldr $ap,[x29,#96] // pull rp + // $acc0-3,$carry hold result, $m0-7 hold modulus + subs $a0,$acc0,$m0 + ldr x30,[x29,#8] // pull return address + sbcs $a1,$acc1,$m1 + stp xzr,xzr,[sp,#8*0] + sbcs $a2,$acc2,$m2 + stp xzr,xzr,[sp,#8*2] + sbcs $a3,$acc3,$m3 + stp xzr,xzr,[sp,#8*4] + sbcs xzr,$carry,xzr // did it borrow? + stp xzr,xzr,[sp,#8*6] + + // $a0-3 hold result-modulus + csel $a0,$acc0,$a0,lo + csel $a1,$acc1,$a1,lo + csel $a2,$acc2,$a2,lo + csel $a3,$acc3,$a3,lo + stp $a0,$a1,[$ap,#8*0] + stp $a2,$a3,[$ap,#8*2] + +.Lmul4x_done: + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldr x29,[sp],#128 + ret +.size __bn_mul4x_mont,.-__bn_mul4x_mont +___ +} +$code.=<<___; +.asciz "Montgomery Multiplication for ARMv8, CRYPTOGAMS by " +.align 4 +___ + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/bn/asm/bn-586.pl b/external/boringssl/crypto/bn/asm/bn-586.pl new file mode 100644 index 0000000000..26d9bcbb09 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/bn/asm/co-586.pl b/external/boringssl/crypto/bn/asm/co-586.pl new file mode 100644 index 0000000000..57101a6bd7 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/bn/asm/rsaz-avx2.pl b/external/boringssl/crypto/bn/asm/rsaz-avx2.pl new file mode 100755 index 0000000000..6b57bd0b67 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/rsaz-avx2.pl @@ -0,0 +1,1945 @@ +#!/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 +# +# 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"; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1. +$avx = 0; +$addx = 0; + +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 indices 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: + vzeroupper + mov %rsp,%r11 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp),%rax +.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 -0x100(%rsp),%rsp + and \$-32, %rsp + lea .Linc(%rip), %r10 + lea -128(%rsp),%rax # control u-op density + + vmovd $power, %xmm4 + vmovdqa (%r10),%ymm0 + vmovdqa 32(%r10),%ymm1 + vmovdqa 64(%r10),%ymm5 + vpbroadcastd %xmm4,%ymm4 + + vpaddd %ymm5, %ymm0, %ymm2 + vpcmpeqd %ymm4, %ymm0, %ymm0 + vpaddd %ymm5, %ymm1, %ymm3 + vpcmpeqd %ymm4, %ymm1, %ymm1 + vmovdqa %ymm0, 32*0+128(%rax) + vpaddd %ymm5, %ymm2, %ymm0 + vpcmpeqd %ymm4, %ymm2, %ymm2 + vmovdqa %ymm1, 32*1+128(%rax) + vpaddd %ymm5, %ymm3, %ymm1 + vpcmpeqd %ymm4, %ymm3, %ymm3 + vmovdqa %ymm2, 32*2+128(%rax) + vpaddd %ymm5, %ymm0, %ymm2 + vpcmpeqd %ymm4, %ymm0, %ymm0 + vmovdqa %ymm3, 32*3+128(%rax) + vpaddd %ymm5, %ymm1, %ymm3 + vpcmpeqd %ymm4, %ymm1, %ymm1 + vmovdqa %ymm0, 32*4+128(%rax) + vpaddd %ymm5, %ymm2, %ymm8 + vpcmpeqd %ymm4, %ymm2, %ymm2 + vmovdqa %ymm1, 32*5+128(%rax) + vpaddd %ymm5, %ymm3, %ymm9 + vpcmpeqd %ymm4, %ymm3, %ymm3 + vmovdqa %ymm2, 32*6+128(%rax) + vpaddd %ymm5, %ymm8, %ymm10 + vpcmpeqd %ymm4, %ymm8, %ymm8 + vmovdqa %ymm3, 32*7+128(%rax) + vpaddd %ymm5, %ymm9, %ymm11 + vpcmpeqd %ymm4, %ymm9, %ymm9 + vpaddd %ymm5, %ymm10, %ymm12 + vpcmpeqd %ymm4, %ymm10, %ymm10 + vpaddd %ymm5, %ymm11, %ymm13 + vpcmpeqd %ymm4, %ymm11, %ymm11 + vpaddd %ymm5, %ymm12, %ymm14 + vpcmpeqd %ymm4, %ymm12, %ymm12 + vpaddd %ymm5, %ymm13, %ymm15 + vpcmpeqd %ymm4, %ymm13, %ymm13 + vpcmpeqd %ymm4, %ymm14, %ymm14 + vpcmpeqd %ymm4, %ymm15, %ymm15 + + vmovdqa -32(%r10),%ymm7 # .Lgather_permd + lea 128($inp), $inp + mov \$9,$power + +.Loop_gather_1024: + vmovdqa 32*0-128($inp), %ymm0 + vmovdqa 32*1-128($inp), %ymm1 + vmovdqa 32*2-128($inp), %ymm2 + vmovdqa 32*3-128($inp), %ymm3 + vpand 32*0+128(%rax), %ymm0, %ymm0 + vpand 32*1+128(%rax), %ymm1, %ymm1 + vpand 32*2+128(%rax), %ymm2, %ymm2 + vpor %ymm0, %ymm1, %ymm4 + vpand 32*3+128(%rax), %ymm3, %ymm3 + vmovdqa 32*4-128($inp), %ymm0 + vmovdqa 32*5-128($inp), %ymm1 + vpor %ymm2, %ymm3, %ymm5 + vmovdqa 32*6-128($inp), %ymm2 + vmovdqa 32*7-128($inp), %ymm3 + vpand 32*4+128(%rax), %ymm0, %ymm0 + vpand 32*5+128(%rax), %ymm1, %ymm1 + vpand 32*6+128(%rax), %ymm2, %ymm2 + vpor %ymm0, %ymm4, %ymm4 + vpand 32*7+128(%rax), %ymm3, %ymm3 + vpand 32*8-128($inp), %ymm8, %ymm0 + vpor %ymm1, %ymm5, %ymm5 + vpand 32*9-128($inp), %ymm9, %ymm1 + vpor %ymm2, %ymm4, %ymm4 + vpand 32*10-128($inp),%ymm10, %ymm2 + vpor %ymm3, %ymm5, %ymm5 + vpand 32*11-128($inp),%ymm11, %ymm3 + vpor %ymm0, %ymm4, %ymm4 + vpand 32*12-128($inp),%ymm12, %ymm0 + vpor %ymm1, %ymm5, %ymm5 + vpand 32*13-128($inp),%ymm13, %ymm1 + vpor %ymm2, %ymm4, %ymm4 + vpand 32*14-128($inp),%ymm14, %ymm2 + vpor %ymm3, %ymm5, %ymm5 + vpand 32*15-128($inp),%ymm15, %ymm3 + lea 32*16($inp), $inp + vpor %ymm0, %ymm4, %ymm4 + vpor %ymm1, %ymm5, %ymm5 + vpor %ymm2, %ymm4, %ymm4 + vpor %ymm3, %ymm5, %ymm5 + + vpor %ymm5, %ymm4, %ymm4 + vextracti128 \$1, %ymm4, %xmm5 # upper half is cleared + vpor %xmm4, %xmm5, %xmm5 + vpermd %ymm5,%ymm7,%ymm5 + vmovdqu %ymm5,($out) + lea 32($out),$out + dec $power + jnz .Loop_gather_1024 + + vpxor %ymm0,%ymm0,%ymm0 + vmovdqu %ymm0,($out) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r11),%xmm6 + movaps -0x98(%r11),%xmm7 + movaps -0x88(%r11),%xmm8 + movaps -0x78(%r11),%xmm9 + movaps -0x68(%r11),%xmm10 + movaps -0x58(%r11),%xmm11 + movaps -0x48(%r11),%xmm12 + movaps -0x38(%r11),%xmm13 + movaps -0x28(%r11),%xmm14 + movaps -0x18(%r11),%xmm15 +.LSEH_end_rsaz_1024_gather5: +___ +$code.=<<___; + lea (%r11),%rsp + 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 +.Linc: + .long 0,0,0,0, 1,1,1,1 + .long 2,2,2,2, 3,3,3,3 + .long 4,4,4,4, 4,4,4,4 +.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->RipRsp + + 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,0x36,0x17,0x0b + .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 + .byte 0x00,0xb3,0x00,0x00 # set_frame r11 +___ +} + +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/external/boringssl/crypto/bn/asm/rsaz-x86_64.pl b/external/boringssl/crypto/bn/asm/rsaz-x86_64.pl new file mode 100755 index 0000000000..c38bde95a3 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/rsaz-x86_64.pl @@ -0,0 +1,2338 @@ +#!/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). +# +# +# 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; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable this after testing. $addx goes up to 1. +$addx = 0; + +($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 + + subq \$`128+24+($win64?0xb0:0)`, %rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,0xa0(%rsp) + movaps %xmm7,0xb0(%rsp) + movaps %xmm8,0xc0(%rsp) + movaps %xmm9,0xd0(%rsp) + movaps %xmm10,0xe0(%rsp) + movaps %xmm11,0xf0(%rsp) + movaps %xmm12,0x100(%rsp) + movaps %xmm13,0x110(%rsp) + movaps %xmm14,0x120(%rsp) + movaps %xmm15,0x130(%rsp) +___ +$code.=<<___; +.Lmul_gather4_body: + movd $pwr,%xmm8 + movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002 + movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000 + + pshufd \$0,%xmm8,%xmm8 # broadcast $power + movdqa %xmm1,%xmm7 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..15 to $power +# +for($i=0;$i<4;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` + movdqa %xmm7,%xmm`$i+3` +___ +} +for(;$i<7;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` +___ +} +$code.=<<___; + pcmpeqd %xmm8,%xmm7 + + movdqa 16*0($bp),%xmm8 + movdqa 16*1($bp),%xmm9 + movdqa 16*2($bp),%xmm10 + movdqa 16*3($bp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4($bp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5($bp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6($bp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7($bp),%xmm15 + leaq 128($bp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 +___ +$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.=<<___; + movq %xmm8,%rbx + + movq $n0, 128(%rsp) # off-load arguments + movq $out, 128+8(%rsp) + movq $mod, 128+16(%rsp) + + movq ($ap), %rax + movq 8($ap), %rcx + mulq %rbx # 0 iteration + movq %rax, (%rsp) + movq %rcx, %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(%rsp), %rdi + movl \$7, %ecx + jmp .Loop_mul_gather + +.align 32 +.Loop_mul_gather: + movdqa 16*0(%rbp),%xmm8 + movdqa 16*1(%rbp),%xmm9 + movdqa 16*2(%rbp),%xmm10 + movdqa 16*3(%rbp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4(%rbp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5(%rbp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6(%rbp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7(%rbp),%xmm15 + leaq 128(%rbp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,%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 + 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_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 128+8(%rsp), $out + movq 128+16(%rsp), %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: + movq %xmm8,%rdx + + mov $n0, 128(%rsp) # off-load arguments + mov $out, 128+8(%rsp) + mov $mod, 128+16(%rsp) + + mulx ($ap), %rbx, %r8 # 0 iteration + mov %rbx, (%rsp) + xor %edi, %edi # cf=0, of=0 + + mulx 8($ap), %rax, %r9 + + mulx 16($ap), %rbx, %r10 + adcx %rax, %r8 + + mulx 24($ap), %rax, %r11 + adcx %rbx, %r9 + + mulx 32($ap), %rbx, %r12 + adcx %rax, %r10 + + mulx 40($ap), %rax, %r13 + adcx %rbx, %r11 + + mulx 48($ap), %rbx, %r14 + adcx %rax, %r12 + + mulx 56($ap), %rax, %r15 + adcx %rbx, %r13 + adcx %rax, %r14 + .byte 0x67 + mov %r8, %rbx + adcx %rdi, %r15 # %rdi is 0 + + mov \$-7, %rcx + jmp .Loop_mulx_gather + +.align 32 +.Loop_mulx_gather: + movdqa 16*0(%rbp),%xmm8 + movdqa 16*1(%rbp),%xmm9 + movdqa 16*2(%rbp),%xmm10 + movdqa 16*3(%rbp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4(%rbp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5(%rbp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6(%rbp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7(%rbp),%xmm15 + leaq 128(%rbp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,%rdx + + .byte 0xc4,0x62,0xfb,0xf6,0x86,0x00,0x00,0x00,0x00 # 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 + + .byte 0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00 # 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 + .byte 0x67 + adox %r15, %r14 + + mulx 56($ap), %rax, %r15 + 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) + + mov 128(%rsp), %rdx # pull arguments + mov 128+8(%rsp), $out + mov 128+16(%rsp), %rbp + + 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 +___ +$code.=<<___ if ($win64); + movaps 0xa0-0xc8(%rax),%xmm6 + movaps 0xb0-0xc8(%rax),%xmm7 + movaps 0xc0-0xc8(%rax),%xmm8 + movaps 0xd0-0xc8(%rax),%xmm9 + movaps 0xe0-0xc8(%rax),%xmm10 + movaps 0xf0-0xc8(%rax),%xmm11 + movaps 0x100-0xc8(%rax),%xmm12 + movaps 0x110-0xc8(%rax),%xmm13 + movaps 0x120-0xc8(%rax),%xmm14 + movaps 0x130-0xc8(%rax),%xmm15 + lea 0xb0(%rax),%rax +___ +$code.=<<___; + 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,8), $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 + + movq %r8, 128*0($inp) # scatter + movq %r9, 128*1($inp) + movq %r10, 128*2($inp) + movq %r11, 128*3($inp) + movq %r12, 128*4($inp) + movq %r13, 128*5($inp) + movq %r14, 128*6($inp) + movq %r15, 128*7($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,8), $out + movl \$8, %r9d + jmp .Loop_scatter +.align 16 +.Loop_scatter: + movq ($inp), %rax + leaq 8($inp), $inp + movq %rax, ($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: +___ +$code.=<<___ if ($win64); +.LSEH_begin_rsaz_512_gather4: + .byte 0x48,0x81,0xec,0xa8,0x00,0x00,0x00 # sub $0xa8,%rsp + .byte 0x0f,0x29,0x34,0x24 # movaps %xmm6,(%rsp) + .byte 0x0f,0x29,0x7c,0x24,0x10 # movaps %xmm7,0x10(%rsp) + .byte 0x44,0x0f,0x29,0x44,0x24,0x20 # movaps %xmm8,0x20(%rsp) + .byte 0x44,0x0f,0x29,0x4c,0x24,0x30 # movaps %xmm9,0x30(%rsp) + .byte 0x44,0x0f,0x29,0x54,0x24,0x40 # movaps %xmm10,0x40(%rsp) + .byte 0x44,0x0f,0x29,0x5c,0x24,0x50 # movaps %xmm11,0x50(%rsp) + .byte 0x44,0x0f,0x29,0x64,0x24,0x60 # movaps %xmm12,0x60(%rsp) + .byte 0x44,0x0f,0x29,0x6c,0x24,0x70 # movaps %xmm13,0x70(%rsp) + .byte 0x44,0x0f,0x29,0xb4,0x24,0x80,0,0,0 # movaps %xmm14,0x80(%rsp) + .byte 0x44,0x0f,0x29,0xbc,0x24,0x90,0,0,0 # movaps %xmm15,0x90(%rsp) +___ +$code.=<<___; + movd $power,%xmm8 + movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002 + movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000 + + pshufd \$0,%xmm8,%xmm8 # broadcast $power + movdqa %xmm1,%xmm7 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..15 to $power +# +for($i=0;$i<4;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` + movdqa %xmm7,%xmm`$i+3` +___ +} +for(;$i<7;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` +___ +} +$code.=<<___; + pcmpeqd %xmm8,%xmm7 + movl \$8, %r9d + jmp .Loop_gather +.align 16 +.Loop_gather: + movdqa 16*0($inp),%xmm8 + movdqa 16*1($inp),%xmm9 + movdqa 16*2($inp),%xmm10 + movdqa 16*3($inp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4($inp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5($inp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6($inp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7($inp),%xmm15 + leaq 128($inp), $inp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,($out) + leaq 8($out), $out + decl %r9d + jnz .Loop_gather +___ +$code.=<<___ if ($win64); + movaps 0x00(%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 + add \$0xa8,%rsp +___ +$code.=<<___; + ret +.LSEH_end_rsaz_512_gather4: +.size rsaz_512_gather4,.-rsaz_512_gather4 + +.align 64 +.Linc: + .long 0,0, 1,1 + .long 2,2, 2,2 +___ +} + +# 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->RipRsp + + 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 + + lea .Lmul_gather4_epilogue(%rip),%rbx + cmp %r10,%rbx + jne .Lse_not_in_mul_gather4 + + lea 0xb0(%rax),%rax + + lea -48-0xa8(%rax),%rsi + lea 512($context),%rdi + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lse_not_in_mul_gather4: + 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 se_handler,.-se_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 + + .rva .LSEH_begin_rsaz_512_gather4 + .rva .LSEH_end_rsaz_512_gather4 + .rva .LSEH_info_rsaz_512_gather4 + +.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[] +.LSEH_info_rsaz_512_gather4: + .byte 0x01,0x46,0x16,0x00 + .byte 0x46,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15 + .byte 0x3d,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14 + .byte 0x34,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13 + .byte 0x2e,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12 + .byte 0x28,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11 + .byte 0x22,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10 + .byte 0x1c,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9 + .byte 0x16,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8 + .byte 0x10,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7 + .byte 0x0b,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6 + .byte 0x07,0x01,0x15,0x00 # sub rsp,0xa8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/bn/asm/x86-mont.pl b/external/boringssl/crypto/bn/asm/x86-mont.pl new file mode 100644 index 0000000000..0626b487f8 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86-mont.pl @@ -0,0 +1,592 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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 "); + +&asm_finish(); diff --git a/external/boringssl/crypto/bn/asm/x86_64-gcc.c b/external/boringssl/crypto/bn/asm/x86_64-gcc.c new file mode 100644 index 0000000000..214c12af88 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86_64-gcc.c @@ -0,0 +1,531 @@ +/* x86_64 BIGNUM accelerator version 0.1, December 2002. + * + * Implemented by Andy Polyakov 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. + */ + +#include + +/* TODO(davidben): Get this file working on Windows x64. */ +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__) + +#include "../internal.h" + + +#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_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; +} + +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; +} + +/* 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 /* !NO_ASM && X86_64 && __GNUC__ */ diff --git a/external/boringssl/crypto/bn/asm/x86_64-mont.pl b/external/boringssl/crypto/bn/asm/x86_64-mont.pl new file mode 100755 index 0000000000..1ca2b1efc0 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86_64-mont.pl @@ -0,0 +1,1430 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable this option after testing. $addx goes up to 1. +$addx = 0; + +# 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,2),%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,2),%rsp # alloca(frame+2*$num) + jmp .Lsqr8x_sp_done + +.align 32 +.Lsqr8x_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 +.Lsqr8x_sp_done: + and \$-64,%rsp + mov $num,%r10 + neg $num + + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.Lsqr8x_body: + + movq $nptr, %xmm2 # save pointer to modulus + pxor %xmm0,%xmm0 + movq $rptr,%xmm1 # save $rptr + movq %r10, %xmm3 # -$num +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%eax + and \$0x80100,%eax + cmp \$0x80100,%eax + jne .Lsqr8x_nox + + call bn_sqrx8x_internal # see x86_64-mont5 module + # %rax top-most carry + # %rbp nptr + # %rcx -8*num + # %r8 end of tp[2*num] + lea (%r8,%rcx),%rbx + mov %rcx,$num + mov %rcx,%rdx + movq %xmm1,$rptr + sar \$3+2,%rcx # %cf=0 + jmp .Lsqr8x_sub + +.align 32 +.Lsqr8x_nox: +___ +$code.=<<___; + call bn_sqr8x_internal # see x86_64-mont5 module + # %rax top-most carry + # %rbp nptr + # %r8 -8*num + # %rdi end of tp[2*num] + lea (%rdi,$num),%rbx + mov $num,%rcx + mov $num,%rdx + movq %xmm1,$rptr + sar \$3+2,%rcx # %cf=0 + jmp .Lsqr8x_sub + +.align 32 +.Lsqr8x_sub: + mov 8*0(%rbx),%r12 + mov 8*1(%rbx),%r13 + mov 8*2(%rbx),%r14 + mov 8*3(%rbx),%r15 + lea 8*4(%rbx),%rbx + sbb 8*0(%rbp),%r12 + sbb 8*1(%rbp),%r13 + sbb 8*2(%rbp),%r14 + sbb 8*3(%rbp),%r15 + lea 8*4(%rbp),%rbp + mov %r12,8*0($rptr) + mov %r13,8*1($rptr) + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + inc %rcx # preserves %cf + jnz .Lsqr8x_sub + + sbb \$0,%rax # top-most carry + lea (%rbx,$num),%rbx # rewind + lea ($rptr,$num),$rptr # rewind + + movq %rax,%xmm1 + pxor %xmm0,%xmm0 + pshufd \$0,%xmm1,%xmm1 + mov 40(%rsp),%rsi # restore %rsp + jmp .Lsqr8x_cond_copy + +.align 32 +.Lsqr8x_cond_copy: + movdqa 16*0(%rbx),%xmm2 + movdqa 16*1(%rbx),%xmm3 + lea 16*2(%rbx),%rbx + movdqu 16*0($rptr),%xmm4 + movdqu 16*1($rptr),%xmm5 + lea 16*2($rptr),$rptr + movdqa %xmm0,-16*2(%rbx) # zero tp + movdqa %xmm0,-16*1(%rbx) + movdqa %xmm0,-16*2(%rbx,%rdx) + movdqa %xmm0,-16*1(%rbx,%rdx) + pcmpeqd %xmm1,%xmm0 + pand %xmm1,%xmm2 + pand %xmm1,%xmm3 + pand %xmm0,%xmm4 + pand %xmm0,%xmm5 + pxor %xmm0,%xmm0 + por %xmm2,%xmm4 + por %xmm3,%xmm5 + movdqu %xmm4,-16*2($rptr) + movdqu %xmm5,-16*1($rptr) + add \$32,$num + jnz .Lsqr8x_cond_copy + + 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 + sbb %r15,%r15 # top-most carry + mov %r14,-1*8($tptr) + + cmp 16(%rsp),$bptr + jne .Lmulx4x_outer + + lea 64(%rsp),$tptr + sub $num,$nptr # rewind $nptr + neg %r15 + mov $num,%rdx + shr \$3+2,$num # %cf=0 + mov 32(%rsp),$rptr # restore rp + jmp .Lmulx4x_sub + +.align 32 +.Lmulx4x_sub: + mov 8*0($tptr),%r11 + mov 8*1($tptr),%r12 + mov 8*2($tptr),%r13 + mov 8*3($tptr),%r14 + lea 8*4($tptr),$tptr + sbb 8*0($nptr),%r11 + sbb 8*1($nptr),%r12 + sbb 8*2($nptr),%r13 + sbb 8*3($nptr),%r14 + lea 8*4($nptr),$nptr + mov %r11,8*0($rptr) + mov %r12,8*1($rptr) + mov %r13,8*2($rptr) + mov %r14,8*3($rptr) + lea 8*4($rptr),$rptr + dec $num # preserves %cf + jnz .Lmulx4x_sub + + sbb \$0,%r15 # top-most carry + lea 64(%rsp),$tptr + sub %rdx,$rptr # rewind + + movq %r15,%xmm1 + pxor %xmm0,%xmm0 + pshufd \$0,%xmm1,%xmm1 + mov 40(%rsp),%rsi # restore %rsp + jmp .Lmulx4x_cond_copy + +.align 32 +.Lmulx4x_cond_copy: + movdqa 16*0($tptr),%xmm2 + movdqa 16*1($tptr),%xmm3 + lea 16*2($tptr),$tptr + movdqu 16*0($rptr),%xmm4 + movdqu 16*1($rptr),%xmm5 + lea 16*2($rptr),$rptr + movdqa %xmm0,-16*2($tptr) # zero tp + movdqa %xmm0,-16*1($tptr) + pcmpeqd %xmm1,%xmm0 + pand %xmm1,%xmm2 + pand %xmm1,%xmm3 + pand %xmm0,%xmm4 + pand %xmm0,%xmm5 + pxor %xmm0,%xmm0 + por %xmm2,%xmm4 + por %xmm3,%xmm5 + movdqu %xmm4,-16*2($rptr) + movdqu %xmm5,-16*1($rptr) + sub \$32,%rdx + jnz .Lmulx4x_cond_copy + + mov %rdx,($tptr) + + 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 " +.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->RipRsp + + 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/external/boringssl/crypto/bn/asm/x86_64-mont5.pl b/external/boringssl/crypto/bn/asm/x86_64-mont5.pl new file mode 100755 index 0000000000..ced3acba51 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86_64-mont5.pl @@ -0,0 +1,3669 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable this after testing. $addx goes up to 1. +$addx = 0; + +# 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 + movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument + lea .Linc(%rip),%r10 + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + lea 2($num),%r11 + neg %r11 + lea -264(%rsp,%r11,8),%rsp # tp=alloca(8*(num+2)+256+8) + and \$-1024,%rsp # minimize TLB usage + + mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp +.Lmul_body: + lea 128($bp),%r12 # reassign $bp (+size optimization) +___ + $bp="%r12"; + $STRIDE=2**5*8; # 5 is "window size" + $N=$STRIDE/4; # should match cache line size +$code.=<<___; + movdqa 0(%r10),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%r10),%xmm1 # 00000002000000020000000200000002 + lea 24-112(%rsp,$num,8),%r10# place the mask after tp[num+3] (+ICache optimization) + and \$-16,%r10 + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + .byte 0x67 + movdqa %xmm4,%xmm3 +___ +for($k=0;$k<$STRIDE/16-4;$k+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($k+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($k+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($k+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($k+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($k+0)+112`(%r10) + + paddd %xmm2,%xmm3 + .byte 0x67 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($k+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($k+2)+112`(%r10) + pand `16*($k+0)-128`($bp),%xmm0 # while it's still in register + + pand `16*($k+1)-128`($bp),%xmm1 + pand `16*($k+2)-128`($bp),%xmm2 + movdqa %xmm3,`16*($k+3)+112`(%r10) + pand `16*($k+3)-128`($bp),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($k=0;$k<$STRIDE/16-4;$k+=4) { +$code.=<<___; + movdqa `16*($k+0)-128`($bp),%xmm4 + movdqa `16*($k+1)-128`($bp),%xmm5 + movdqa `16*($k+2)-128`($bp),%xmm2 + pand `16*($k+0)+112`(%r10),%xmm4 + movdqa `16*($k+3)-128`($bp),%xmm3 + pand `16*($k+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($k+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($k+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + por %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bp),$bp + 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 + + 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 # note that upon exit $j==$num, so + # they can be used interchangeably + + add %rax,$hi1 + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $hi1,-16(%rsp,$num,8) # tp[num-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: + lea 24+128(%rsp,$num,8),%rdx # where 256-byte mask is (+size optimization) + and \$-16,%rdx + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($k=0;$k<$STRIDE/16;$k+=4) { +$code.=<<___; + movdqa `16*($k+0)-128`($bp),%xmm0 + movdqa `16*($k+1)-128`($bp),%xmm1 + movdqa `16*($k+2)-128`($bp),%xmm2 + movdqa `16*($k+3)-128`($bp),%xmm3 + pand `16*($k+0)-128`(%rdx),%xmm0 + pand `16*($k+1)-128`(%rdx),%xmm1 + por %xmm0,%xmm4 + pand `16*($k+2)-128`(%rdx),%xmm2 + por %xmm1,%xmm5 + pand `16*($k+3)-128`(%rdx),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bp),$bp + + mov ($ap),%rax # ap[0] + movq %xmm0,$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 # note that upon exit $j==$num, so + # they can be used interchangeably + add %rax,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$num,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$num,8) # tp[num-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 + + 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 \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + je .Lmulx4x_enter +___ +$code.=<<___; + .byte 0x67 + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + .byte 0x67 + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num # -$num + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra [num] is allocated in order + # to align with bn_power5's frame, which is cleansed after + # completing exponentiation. Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rp,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lmul4xsp_alt + sub %r11,%rsp # align with $rp + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + jmp .Lmul4xsp_done + +.align 32 +.Lmul4xsp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + 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 + + 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 # $num was in bytes + movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument, index + lea .Linc(%rip),%rax + lea 128(%rdx,$num),%r13 # end of powers table (+size optimization) + 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.=<<___; + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 88-112(%rsp,$num),%r10 # place the mask after tp[num+1] (+ICache optimization) + lea 128(%rdx),$bp # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + .byte 0x67,0x67 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + .byte 0x67 + movdqa %xmm4,%xmm3 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($i+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($i+0)+112`(%r10) + + paddd %xmm2,%xmm3 + .byte 0x67 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($i+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($i+2)+112`(%r10) + pand `16*($i+0)-128`($bp),%xmm0 # while it's still in register + + pand `16*($i+1)-128`($bp),%xmm1 + pand `16*($i+2)-128`($bp),%xmm2 + movdqa %xmm3,`16*($i+3)+112`(%r10) + pand `16*($i+3)-128`($bp),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bp),%xmm4 + movdqa `16*($i+1)-128`($bp),%xmm5 + movdqa `16*($i+2)-128`($bp),%xmm2 + pand `16*($i+0)+112`(%r10),%xmm4 + movdqa `16*($i+3)-128`($bp),%xmm3 + pand `16*($i+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($i+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($i+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + por %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[0] + + 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 + + imulq $A[0],$m1 # "tp[0]"*n0 + lea 64+8(%rsp),$tp + mov %rdx,$A[1] + + 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 8*1($np),%rax + 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 8*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 -8*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 -8*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 8*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 8*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 8*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 -8*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 -8*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] + + lea ($np,$num),$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: + lea 16+128($tp),%rdx # where 256-byte mask is (+size optimization) + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bp),%xmm0 + movdqa `16*($i+1)-128`($bp),%xmm1 + movdqa `16*($i+2)-128`($bp),%xmm2 + movdqa `16*($i+3)-128`($bp),%xmm3 + pand `16*($i+0)-128`(%rdx),%xmm0 + pand `16*($i+1)-128`(%rdx),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)-128`(%rdx),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)-128`(%rdx),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[i] + + 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 + + imulq $A[0],$m1 # tp[0]*n0 + mov %rdx,$A[1] + mov $N[1],($tp) # store upmost overflow bit + + lea ($tp,$num),$tp # rewind $tp + + 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 8*1($np),%rax + 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 8*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 -8*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 -8*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 8*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 8*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 8*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 -8*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 -8*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] + + mov $N[1],-16($tp) # tp[j-1] + lea ($np,$num),$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.=<<___; + xor %rax,%rax + sub $N[0],$m1 # compare top-most words + adc $j,$j # $j is zero + or $j,$N[1] + sub $N[1],%rax # %rax=-$N[1] + lea ($tp,$num),%rbx # tptr in .sqr4x_sub + mov ($np),%r12 + lea ($np),%rbp # nptr in .sqr4x_sub + mov %r9,%rcx + sar \$3+2,%rcx + mov 56+8(%rsp),%rdi # rptr in .sqr4x_sub + dec %r12 # so that after 'not' we get -n[0] + xor %r10,%r10 + mov 8*1(%rbp),%r13 + mov 8*2(%rbp),%r14 + mov 8*3(%rbp),%r15 + jmp .Lsqr4x_sub_entry +___ +} 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 \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + je .Lpowerx5_enter +___ +$code.=<<___; + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10d # 3*$num + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lpwr_sp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + jmp .Lpwr_sp_done + +.align 32 +.Lpwr_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + 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, used in sqr8x + movq $nptr,%xmm2 # save $nptr + movq %r10, %xmm3 # -$num, used in sqr8x + movq $bptr,%xmm4 + + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_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 +__bn_sqr8x_reduction: + xor %rax,%rax + lea ($nptr,$num),%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 8*0($nptr),%rax # n[0] + mov \$8,%ecx + jmp .L8x_reduce + +.align 32 +.L8x_reduce: + mulq $m0 + mov 8*1($nptr),%rax # n[1] + neg %r8 + mov %rdx,%r8 + adc \$0,%r8 + + mulq $m0 + add %rax,%r9 + mov 8*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 8*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 8*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 8*5($nptr),%rax + adc \$0,%rdx + add %r12,%r11 + mov %rdx,%r12 + adc \$0,%r12 + + mulq $m0 + add %rax,%r13 + mov 8*6($nptr),%rax + adc \$0,%rdx + add %r13,%r12 + mov %rdx,%r13 + adc \$0,%r13 + + mulq $m0 + add %rax,%r14 + mov 8*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 8*0($nptr),%rax # n[0] + adc \$0,%rdx + add %r15,%r14 + mov %rdx,%r15 + adc \$0,%r15 + + dec %ecx + jnz .L8x_reduce + + lea 8*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 8*0($nptr),%rax + jmp .L8x_tail + +.align 32 +.L8x_tail: + mulq $m0 + add %rax,%r8 + mov 8*1($nptr),%rax + mov %r8,($tptr) # save result + mov %rdx,%r8 + adc \$0,%r8 + + mulq $m0 + add %rax,%r9 + mov 8*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 8*3($nptr),%rax + adc \$0,%rdx + add %r10,%r9 + mov %rdx,%r10 + adc \$0,%r10 + + mulq $m0 + add %rax,%r11 + mov 8*4($nptr),%rax + adc \$0,%rdx + add %r11,%r10 + mov %rdx,%r11 + adc \$0,%r11 + + mulq $m0 + add %rax,%r12 + mov 8*5($nptr),%rax + adc \$0,%rdx + add %r12,%r11 + mov %rdx,%r12 + adc \$0,%r12 + + mulq $m0 + add %rax,%r13 + mov 8*6($nptr),%rax + adc \$0,%rdx + add %r13,%r12 + mov %rdx,%r13 + adc \$0,%r13 + + mulq $m0 + add %rax,%r14 + mov 8*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 8*0($nptr),%rax # pull n[0] + mov %rdx,%r15 + adc \$0,%r15 + + dec %ecx + jnz .L8x_tail + + lea 8*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? + adc \$0,%r9 + adc \$0,%r10 + adc \$0,%r11 + adc \$0,%r12 + adc \$0,%r13 + adc \$0,%r14 + adc \$0,%r15 # can't overflow, because we + # started with "overhung" part + # of multiplication + 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 -8($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 + ret +.size bn_sqr8x_internal,.-bn_sqr8x_internal +___ +} +############################################################## +# Post-condition, 4x unrolled +# +{ +my ($tptr,$nptr)=("%rbx","%rbp"); +$code.=<<___; +.type __bn_post4x_internal,\@abi-omnipotent +.align 32 +__bn_post4x_internal: + mov 8*0($nptr),%r12 + lea (%rdi,$num),$tptr # %rdi was $tptr above + mov $num,%rcx + movq %xmm1,$rptr # restore $rptr + neg %rax + movq %xmm1,$aptr # prepare for back-to-back call + sar \$3+2,%rcx + dec %r12 # so that after 'not' we get -n[0] + xor %r10,%r10 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 + jmp .Lsqr4x_sub_entry + +.align 16 +.Lsqr4x_sub: + mov 8*0($nptr),%r12 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 +.Lsqr4x_sub_entry: + lea 8*4($nptr),$nptr + not %r12 + not %r13 + not %r14 + not %r15 + and %rax,%r12 + and %rax,%r13 + and %rax,%r14 + and %rax,%r15 + + neg %r10 # mov %r10,%cf + adc 8*0($tptr),%r12 + adc 8*1($tptr),%r13 + adc 8*2($tptr),%r14 + adc 8*3($tptr),%r15 + mov %r12,8*0($rptr) + lea 8*4($tptr),$tptr + mov %r13,8*1($rptr) + sbb %r10,%r10 # mov %cf,%r10 + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + + inc %rcx # pass %cf + jnz .Lsqr4x_sub + + mov $num,%r10 # prepare for back-to-back call + neg $num # restore $num + ret +.size __bn_post4x_internal,.-__bn_post4x_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 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). The stack is allocated to aligned with + # bn_power5's frame, and as bn_from_montgomery happens to be + # last operation, we use the opportunity to cleanse it. + # + lea -320(%rsp,$num,2),%r11 + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lfrom_sp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + jmp .Lfrom_sp_done + +.align 32 +.Lfrom_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + 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 \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + jne .Lfrom_mont_nox + + lea (%rax,$num),$rptr + call __bn_sqrx8x_reduction + call __bn_postx4x_internal + + pxor %xmm0,%xmm0 + lea 48(%rsp),%rax + mov 40(%rsp),%rsi # restore %rsp + jmp .Lfrom_mont_zero + +.align 32 +.Lfrom_mont_nox: +___ +$code.=<<___; + call __bn_sqr8x_reduction + call __bn_post4x_internal + + 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: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num # -$num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra [num] is allocated in order + # to align with bn_power5's frame, which is cleansed after + # completing exponentiation. Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rp,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lmulx4xsp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + jmp .Lmulx4xsp_done + +.Lmulx4xsp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + 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 + + 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: + mov $num,8(%rsp) # save -$num (it was in bytes) + mov $num,%r10 + neg $num # restore $num + shl \$5,$num + neg %r10 # restore $num + lea 128($bp,$num),%r13 # end of powers table (+size optimization) + shr \$5+5,$num + movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument + sub \$1,$num + lea .Linc(%rip),%rax + 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.=<<___; + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 88-112(%rsp,%r10),%r10 # place the mask after tp[num+1] (+ICache optimizaton) + lea 128($bp),$bptr # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + .byte 0x67 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + .byte 0x67 + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + movdqa %xmm4,%xmm3 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($i+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + .byte 0x67 + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($i+0)+112`(%r10) + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($i+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($i+2)+112`(%r10) + + pand `16*($i+0)-128`($bptr),%xmm0 # while it's still in register + pand `16*($i+1)-128`($bptr),%xmm1 + pand `16*($i+2)-128`($bptr),%xmm2 + movdqa %xmm3,`16*($i+3)+112`(%r10) + pand `16*($i+3)-128`($bptr),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bptr),%xmm4 + movdqa `16*($i+1)-128`($bptr),%xmm5 + movdqa `16*($i+2)-128`($bptr),%xmm2 + pand `16*($i+0)+112`(%r10),%xmm4 + movdqa `16*($i+3)-128`($bptr),%xmm3 + pand `16*($i+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($i+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($i+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + pxor %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bptr),$bptr + movq %xmm0,%rdx # bp[0] + lea 64+8*4+8(%rsp),$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 + + mov $bptr,8+8(%rsp) # off-load &b[i] + + lea 4*8($aptr),$aptr + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + + 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 24+8(%rsp),$bptr # counter value + mov %r10,-8*4($tptr) + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-8*3($tptr) + adcx %rax,%r12 + adox $zero,%r15 # of=0 + lea 4*8($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*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 8(%rsp),$num # load -num + 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: + lea 16-256($tptr),%r10 # where 256-byte mask is (+density control) + pxor %xmm4,%xmm4 + .byte 0x67,0x67 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bptr),%xmm0 + movdqa `16*($i+1)-128`($bptr),%xmm1 + movdqa `16*($i+2)-128`($bptr),%xmm2 + pand `16*($i+0)+256`(%r10),%xmm0 + movdqa `16*($i+3)-128`($bptr),%xmm3 + pand `16*($i+1)+256`(%r10),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)+256`(%r10),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)+256`(%r10),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bptr),$bptr + movq %xmm0,%rdx # m0=bp[i] + + 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),$nptr # rewind $nptr + lea 4*8($aptr),$aptr + adox -1*8($tptr),%r13 + adcx $zero,%r14 + adox $zero,%r14 + + mov $mi,%r15 + imulq 32+8(%rsp),$mi # "t[0]"*n0 + + mov $mi,%rdx + xor $zero,$zero # cf=0, of=0 + mov $bptr,8+8(%rsp) # off-load &b[i] + + 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 + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov 24+8(%rsp),$bptr # counter value + mov %r10,-8*4($tptr) + adcx %rax,%r12 + mov %r11,-8*3($tptr) + adox $zero,%r15 # of=0 + mov %r12,-8*2($tptr) + lea 4*8($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*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 + mov %r11,-4*8($tptr) + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + lea 4*8($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 + 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 -8($nptr),%r10 + mov $zero,%r8 + mov ($nptr,$num),%r12 + lea ($nptr,$num),%rbp # rewind $nptr + mov $num,%rcx + lea ($tptr,$num),%rdi # rewind $tptr + xor %eax,%eax + xor %r15,%r15 + sub %r14,%r10 # compare top-most words + adc %r15,%r15 + or %r15,%r8 + sar \$3+2,%rcx + sub %r8,%rax # %rax=-%r8 + mov 56+8(%rsp),%rdx # restore rp + dec %r12 # so that after 'not' we get -n[0] + mov 8*1(%rbp),%r13 + xor %r8,%r8 + mov 8*2(%rbp),%r14 + mov 8*3(%rbp),%r15 + jmp .Lsqrx4x_sub_entry # 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: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lpwrx_sp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + jmp .Lpwrx_sp_done + +.align 32 +.Lpwrx_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + 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_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_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 + + 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 +__bn_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 -8*8($nptr,$num),%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 8*0($nptr),%rax,%r8 # n[0] + adcx %rbx,%rax # discarded + adox %r9,%r8 + + mulx 8*1($nptr),%rbx,%r9 # n[1] + adcx %rbx,%r8 + adox %r10,%r9 + + mulx 8*2($nptr),%rbx,%r10 + adcx %rbx,%r9 + adox %r11,%r10 + + mulx 8*3($nptr),%rbx,%r11 + adcx %rbx,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*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 8*5($nptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 8*6($nptr),%rax,%r14 + adcx %rax,%r13 + adox %r15,%r14 + + mulx 8*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 8*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 8*0($nptr),%rax,%r8 + adcx %rax,%rbx + adox %r9,%r8 + + mulx 8*1($nptr),%rax,%r9 + adcx %rax,%r8 + adox %r10,%r9 + + mulx 8*2($nptr),%rax,%r10 + adcx %rax,%r9 + adox %r11,%r10 + + mulx 8*3($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rax,%r12 + adcx %rax,%r11 + adox %r13,%r12 + + mulx 8*5($nptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 8*6($nptr),%rax,%r14 + adcx %rax,%r13 + adox %r15,%r14 + + mulx 8*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 8*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? + adc \$0,%r9 + adc \$0,%r10 + adc \$0,%r11 + adc \$0,%r12 + adc \$0,%r13 + adc \$0,%r14 + adc \$0,%r15 # can't overflow, because we + # started with "overhung" part + # of multiplication + 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 8*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 + ret +.size bn_sqrx8x_internal,.-bn_sqrx8x_internal +___ +} +############################################################## +# Post-condition, 4x unrolled +# +{ +my ($rptr,$nptr)=("%rdx","%rbp"); +$code.=<<___; +.align 32 +__bn_postx4x_internal: + mov 8*0($nptr),%r12 + mov %rcx,%r10 # -$num + mov %rcx,%r9 # -$num + neg %rax + sar \$3+2,%rcx + #lea 48+8(%rsp,%r9),$tptr + movq %xmm1,$rptr # restore $rptr + movq %xmm1,$aptr # prepare for back-to-back call + dec %r12 # so that after 'not' we get -n[0] + mov 8*1($nptr),%r13 + xor %r8,%r8 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 + jmp .Lsqrx4x_sub_entry + +.align 16 +.Lsqrx4x_sub: + mov 8*0($nptr),%r12 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 +.Lsqrx4x_sub_entry: + andn %rax,%r12,%r12 + lea 8*4($nptr),$nptr + andn %rax,%r13,%r13 + andn %rax,%r14,%r14 + andn %rax,%r15,%r15 + + neg %r8 # mov %r8,%cf + adc 8*0($tptr),%r12 + adc 8*1($tptr),%r13 + adc 8*2($tptr),%r14 + adc 8*3($tptr),%r15 + mov %r12,8*0($rptr) + lea 8*4($tptr),$tptr + mov %r13,8*1($rptr) + sbb %r8,%r8 # mov %cf,%r8 + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + + inc %rcx + jnz .Lsqrx4x_sub + + neg %r9 # restore $num + + ret +.size __bn_postx4x_internal,.-__bn_postx4x_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 32 +bn_gather5: +.LSEH_begin_bn_gather5: # Win64 thing, but harmless in other cases + # I can't trust assembler to use specific encoding:-( + .byte 0x4c,0x8d,0x14,0x24 #lea (%rsp),%r10 + .byte 0x48,0x81,0xec,0x08,0x01,0x00,0x00 #sub $0x108,%rsp + lea .Linc(%rip),%rax + and \$-16,%rsp # shouldn't be formally required + + movd $idx,%xmm5 + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 128($tbl),%r11 # size optimization + lea 128(%rsp),%rax # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast $idx + movdqa %xmm1,%xmm4 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to $idx and save result to stack +# +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 +___ +$code.=<<___ if ($i); + movdqa %xmm3,`16*($i-1)-128`(%rax) +___ +$code.=<<___; + movdqa %xmm4,%xmm3 + + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)-128`(%rax) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)-128`(%rax) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)-128`(%rax) + movdqa %xmm4,%xmm2 +___ +} +$code.=<<___; + movdqa %xmm3,`16*($i-1)-128`(%rax) + jmp .Lgather + +.align 32 +.Lgather: + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`(%r11),%xmm0 + movdqa `16*($i+1)-128`(%r11),%xmm1 + movdqa `16*($i+2)-128`(%r11),%xmm2 + pand `16*($i+0)-128`(%rax),%xmm0 + movdqa `16*($i+3)-128`(%r11),%xmm3 + pand `16*($i+1)-128`(%rax),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)-128`(%rax),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)-128`(%rax),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + lea $STRIDE(%r11),%r11 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + movq %xmm0,($out) # m0=bp[0] + lea 8($out),$out + sub \$1,$num + jnz .Lgather + + lea (%r10),%rsp + ret +.LSEH_end_bn_gather5: +.size bn_gather5,.-bn_gather5 +___ +} +$code.=<<___; +.align 64 +.Linc: + .long 0,0, 1,1 + .long 2,2, 2,2 +.asciz "Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by " +___ + +# 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->RipRsp + + 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 + ja .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: + 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 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,0x0b,0x03,0x0a + .byte 0x0b,0x01,0x21,0x00 # sub rsp,0x108 + .byte 0x04,0xa3,0x00,0x00 # lea r10,(rsp) +.align 8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/bn/bn.c b/external/boringssl/crypto/bn/bn.c new file mode 100644 index 0000000000..0ecaf8252d --- /dev/null +++ b/external/boringssl/crypto/bn/bn.c @@ -0,0 +1,353 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include + +#include "internal.h" + + +BIGNUM *BN_new(void) { + BIGNUM *bn = OPENSSL_malloc(sizeof(BIGNUM)); + + if (bn == NULL) { + OPENSSL_PUT_ERROR(BN, 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->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 kOneLimbs[1] = { 1 }; + static const BIGNUM kOne = STATIC_BIGNUM(kOneLimbs); + + return &kOne; +} + +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_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) { + if (bn_wexpand(bn, num) == NULL) { + return 0; + } + memmove(bn->d, words, num * sizeof(BN_ULONG)); + /* |bn_wexpand| verified that |num| isn't too large. */ + bn->top = (int)num; + bn_correct_top(bn); + bn->neg = 0; + 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, size_t words) { + BN_ULONG *a; + + if (words <= (size_t)bn->dmax) { + return bn; + } + + if (words > (INT_MAX / (4 * BN_BITS2))) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return NULL; + } + + if (bn->flags & BN_FLG_STATIC_DATA) { + OPENSSL_PUT_ERROR(BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + return NULL; + } + + a = OPENSSL_malloc(sizeof(BN_ULONG) * words); + if (a == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top); + + OPENSSL_free(bn->d); + bn->d = a; + bn->dmax = (int)words; + + return bn; +} + +BIGNUM *bn_expand(BIGNUM *bn, size_t bits) { + if (bits + BN_BITS2 - 1 < bits) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return NULL; + } + 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/external/boringssl/crypto/bn/bn_asn1.c b/external/boringssl/crypto/bn/bn_asn1.c new file mode 100644 index 0000000000..efb23355b9 --- /dev/null +++ b/external/boringssl/crypto/bn/bn_asn1.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + + +int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) { + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) || + CBS_len(&child) == 0) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return 0; + } + + if (CBS_data(&child)[0] & 0x80) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + /* INTEGERs must be minimal. */ + if (CBS_data(&child)[0] == 0x00 && + CBS_len(&child) > 1 && + !(CBS_data(&child)[1] & 0x80)) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return 0; + } + + return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL; +} + +int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) { + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) || + CBS_len(&child) == 0) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return 0; + } + + /* This function intentionally does not reject negative numbers or non-minimal + * encodings. Estonian IDs issued between September 2014 to September 2015 are + * broken. See https://crbug.com/532048 and https://crbug.com/534766. + * + * TODO(davidben): Remove this code and callers in March 2016. */ + return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL; +} + +int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) { + /* Negative numbers are unsupported. */ + if (BN_is_negative(bn)) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) || + /* The number must be padded with a leading zero if the high bit would + * otherwise be set or if |bn| is zero. */ + (BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) || + !BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/bn/bn_test.cc b/external/boringssl/crypto/bn/bn_test.cc new file mode 100644 index 0000000000..d909ee2803 --- /dev/null +++ b/external/boringssl/crypto/bn/bn_test.cc @@ -0,0 +1,1943 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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. */ + +/* For BIGNUM format macros. */ +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "../crypto/test/scoped_types.h" +#include "../crypto/test/test_util.h" + + +// This program tests the BIGNUM implementation. It takes an optional -bc +// argument to write a transcript compatible with the UNIX bc utility. +// +// TODO(davidben): Rather than generate random inputs and depend on bc to check +// the results, most of these tests should use known answers. + +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 + +static bool test_add(FILE *fp); +static bool test_sub(FILE *fp); +static bool test_lshift1(FILE *fp); +static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a); +static bool test_rshift1(FILE *fp); +static bool test_rshift(FILE *fp, BN_CTX *ctx); +static bool test_sqr(FILE *fp, BN_CTX *ctx); +static bool test_mul(FILE *fp); +static bool test_div(FILE *fp, BN_CTX *ctx); +static int rand_neg(); + +static bool test_div_word(FILE *fp); +static bool test_mont(FILE *fp, BN_CTX *ctx); +static bool test_mod(FILE *fp, BN_CTX *ctx); +static bool test_mod_mul(FILE *fp, BN_CTX *ctx); +static bool test_mod_exp(FILE *fp, BN_CTX *ctx); +static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx); +static bool test_exp(FILE *fp, BN_CTX *ctx); +static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx); +static bool test_exp_mod_zero(void); +static bool test_small_prime(FILE *fp, BN_CTX *ctx); +static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx); +static bool test_sqrt(FILE *fp, BN_CTX *ctx); +static bool test_bn2bin_padded(BN_CTX *ctx); +static bool test_dec2bn(BN_CTX *ctx); +static bool test_hex2bn(BN_CTX *ctx); +static bool test_asc2bn(BN_CTX *ctx); +static bool test_mpi(); +static bool test_rand(); +static bool test_asn1(); + +static const uint8_t kSample[] = + "\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"; + +// A wrapper around puts that takes its arguments in the same order as our *_fp +// functions. +static void puts_fp(FILE *out, const char *m) { + if (out != nullptr) { + fputs(m, out); + } +} + +static void flush_fp(FILE *out) { + if (out != nullptr) { + fflush(out); + } +} + +static void message(FILE *out, const char *m) { + puts_fp(out, "print \"test "); + puts_fp(out, m); + puts_fp(out, "\\n\"\n"); +} + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + ScopedFILE bc_file; + argc--; + argv++; + while (argc >= 1) { + if (strcmp(*argv, "-bc") == 0) { + if (argc < 2) { + fprintf(stderr, "Missing parameter to -bc\n"); + return 1; + } + bc_file.reset(fopen(argv[1], "w+")); + if (!bc_file) { + fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); + } + argc--; + argv++; + } else { + fprintf(stderr, "Unknown option: %s\n", argv[0]); + return 1; + } + argc--; + argv++; + } + + + ScopedBN_CTX ctx(BN_CTX_new()); + if (!ctx) { + return 1; + } + + puts_fp(bc_file.get(), "/* This script, when run through the UNIX bc utility, " + "should produce a sequence of zeros. */\n"); + puts_fp(bc_file.get(), "/* tr a-f A-F < bn_test.out | sed s/BAsE/base/ | bc " + "| grep -v 0 */\n"); + puts_fp(bc_file.get(), "obase=16\nibase=16\n"); + + message(bc_file.get(), "BN_add"); + if (!test_add(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_sub"); + if (!test_sub(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_lshift1"); + if (!test_lshift1(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_lshift (fixed)"); + ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL)); + if (!sample) { + return 1; + } + if (!test_lshift(bc_file.get(), ctx.get(), std::move(sample))) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_lshift"); + if (!test_lshift(bc_file.get(), ctx.get(), nullptr)) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_rshift1"); + if (!test_rshift1(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_rshift"); + if (!test_rshift(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_sqr"); + if (!test_sqr(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mul"); + if (!test_mul(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_div"); + if (!test_div(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_div_word"); + if (!test_div_word(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod"); + if (!test_mod(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_mul"); + if (!test_mod_mul(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mont"); + if (!test_mont(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_exp"); + if (!test_mod_exp(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_exp_mont_consttime"); + if (!test_mod_exp_mont_consttime(bc_file.get(), ctx.get()) || + !test_mod_exp_mont5(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_exp"); + if (!test_exp(bc_file.get(), ctx.get()) || + !test_exp_mod_zero()) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_sqrt"); + if (!test_mod_sqrt(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "Small prime generation"); + if (!test_small_prime(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_sqrt"); + if (!test_sqrt(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + if (!test_bn2bin_padded(ctx.get()) || + !test_dec2bn(ctx.get()) || + !test_hex2bn(ctx.get()) || + !test_asc2bn(ctx.get()) || + !test_mpi() || + !test_rand() || + !test_asn1()) { + return 1; + } + + printf("PASS\n"); + return 0; +} + +static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) { + BIGNUM *raw = NULL; + int ret = BN_hex2bn(&raw, in); + out->reset(raw); + return ret; +} + +static bool test_add(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_rand(b.get(), 450 + i, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_add(c.get(), a.get(), b.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " + "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + a->neg = !a->neg; + b->neg = !b->neg; + if (!BN_add(c.get(), c.get(), b.get()) || + !BN_add(c.get(), c.get(), a.get())) { + return false; + } + if (!BN_is_zero(c.get())) { + fprintf(stderr, "Add test failed!\n"); + return false; + } + } + return true; +} + +static bool test_sub(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c) { + return false; + } + + for (int i = 0; i < num0 + num1; i++) { + if (i < num1) { + if (!BN_rand(a.get(), 512, 0, 0) || + !BN_copy(b.get(), a.get()) || + !BN_set_bit(a.get(), i) || + !BN_add_word(b.get(), i)) { + return false; + } + } else { + if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + } + if (!BN_sub(c.get(), a.get(), b.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_add(c.get(), c.get(), b.get()) || + !BN_sub(c.get(), c.get(), a.get())) { + return false; + } + if (!BN_is_zero(c.get())) { + fprintf(stderr, "Subtract test failed!\n"); + return false; + } + } + return true; +} + +static bool test_div(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get())) { + return false; + } + BN_zero(b.get()); + if (BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + fprintf(stderr, "Division by zero succeeded!\n"); + return false; + } + ERR_clear_error(); + + for (int i = 0; i < num0 + num1; i++) { + if (i < num1) { + if (!BN_rand(a.get(), 400, 0, 0) || + !BN_copy(b.get(), a.get()) || + !BN_lshift(a.get(), a.get(), i) || + !BN_add_word(a.get(), i)) { + return false; + } + } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + + BN_print_fp(fp, a.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(e.get(), d.get(), b.get(), ctx) || + !BN_add(d.get(), e.get(), c.get()) || + !BN_sub(d.get(), d.get(), a.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Division test failed!\n"); + return false; + } + } + + // Test that BN_div never gives negative zero in the quotient. + if (!BN_set_word(a.get(), 1) || + !BN_set_word(b.get(), 2)) { + return false; + } + BN_set_negative(a.get(), 1); + if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) { + fprintf(stderr, "Division test failed!\n"); + return false; + } + + // Test that BN_div never gives negative zero in the remainder. + if (!BN_set_word(b.get(), 1)) { + return false; + } + if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { + fprintf(stderr, "Division test failed!\n"); + return false; + } + + return true; +} + +static bool test_lshift1(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + for (int i = 0; i < num0; i++) { + if (!BN_lshift1(b.get(), a.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * 2"); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_add(c.get(), a.get(), a.get()) || + !BN_sub(a.get(), b.get(), c.get())) { + return false; + } + if (!BN_is_zero(a.get())) { + fprintf(stderr, "Left shift one test failed!\n"); + return false; + } + + if (!BN_copy(a.get(), b.get())) { + return false; + } + } + return true; +} + +static bool test_rshift(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e || !BN_one(c.get()) || + !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + for (int i = 0; i < num0; i++) { + if (!BN_rshift(b.get(), a.get(), i + 1) || + !BN_add(c.get(), c.get(), c.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) || + !BN_sub(d.get(), d.get(), b.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Right shift test failed!\n"); + return false; + } + } + return true; +} + +static bool test_rshift1(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + + for (int i = 0; i < num0; i++) { + if (!BN_rshift1(b.get(), a.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / 2"); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_sub(c.get(), a.get(), b.get()) || + !BN_sub(c.get(), c.get(), b.get())) { + return false; + } + if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) { + fprintf(stderr, "Right shift one test failed!\n"); + return false; + } + if (!BN_copy(a.get(), b.get())) { + return false; + } + } + return true; +} + +static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a) { + if (!a) { + a.reset(BN_new()); + if (!a || !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + } + + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + if (!b || !c || !d || !BN_one(c.get())) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_lshift(b.get(), a.get(), i + 1) || + !BN_add(c.get(), c.get(), c.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), c.get(), ctx) || + !BN_sub(d.get(), d.get(), b.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Left shift test failed!\n"); + fprintf(stderr, "a="); + BN_print_fp(stderr, a.get()); + fprintf(stderr, "\nb="); + BN_print_fp(stderr, b.get()); + fprintf(stderr, "\nc="); + BN_print_fp(stderr, c.get()); + fprintf(stderr, "\nd="); + BN_print_fp(stderr, d.get()); + fprintf(stderr, "\n"); + return false; + } + } + return true; +} + +static bool test_mul(FILE *fp) { + ScopedBN_CTX ctx(BN_CTX_new()); + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!ctx || !a || !b || !c || !d || !e) { + return false; + } + + for (int i = 0; i < num0 + num1; i++) { + if (i <= num1) { + if (!BN_rand(a.get(), 100, 0, 0) || + !BN_rand(b.get(), 100, 0, 0)) { + return false; + } + } else if (!BN_rand(b.get(), i - num1, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) || + !BN_sub(d.get(), d.get(), b.get())) { + return false; + } + if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) { + fprintf(stderr, "Multiplication test failed!\n"); + return false; + } + } + + // Test that BN_mul never gives negative zero. + if (!BN_set_word(a.get(), 1)) { + return false; + } + BN_set_negative(a.get(), 1); + BN_zero(b.get()); + if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) { + return false; + } + if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { + fprintf(stderr, "Multiplication test failed!\n"); + return false; + } + + return true; +} + +static bool test_sqr(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !c || !d || !e) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) { + return false; + } + a->neg = rand_neg(); + if (!BN_sqr(c.get(), a.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) || + !BN_sub(d.get(), d.get(), a.get())) { + return false; + } + if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) { + fprintf(stderr, "Square test failed!\n"); + return false; + } + } + + // Regression test for a BN_sqr overflow bug. + BIGNUM *a_raw = a.get(); + if (!BN_hex2bn( + &a_raw, + "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") || + !BN_sqr(c.get(), a.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), a.get(), ctx)) { + return false; + } + if (BN_cmp(c.get(), d.get())) { + fprintf(stderr, + "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + return false; + } + + // Regression test for a BN_sqr overflow bug. + a_raw = a.get(); + if (!BN_hex2bn( + &a_raw, + "80000000000000000000000080000001FFFFFFFE000000000000000000000000") || + !BN_sqr(c.get(), a.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), a.get(), ctx)) { + return false; + } + if (BN_cmp(c.get(), d.get())) { + fprintf(stderr, + "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + return false; + } + + return true; +} + + +static int rand_neg() { + static unsigned int neg = 0; + static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1}; + + return sign[(neg++) % 8]; +} + +static void print_word(FILE *fp, BN_ULONG w) { + fprintf(fp, BN_HEX_FMT1, w); +} + +static bool test_div_word(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + if (!a || !b) { + return false; + } + + for (int i = 0; i < num0; i++) { + do { + if (!BN_rand(a.get(), 512, -1, 0) || + !BN_rand(b.get(), BN_BITS2, -1, 0)) { + return false; + } + } while (BN_is_zero(b.get())); + + if (!BN_copy(b.get(), a.get())) { + return false; + } + BN_ULONG s = b->d[0]; + BN_ULONG rmod = BN_mod_word(b.get(), s); + BN_ULONG r = BN_div_word(b.get(), s); + if (r == (BN_ULONG)-1) { + return false; + } + + if (rmod != r) { + fprintf(stderr, "Mod (word) test failed!\n"); + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / "); + print_word(fp, s); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + + BN_print_fp(fp, a.get()); + puts_fp(fp, " % "); + print_word(fp, s); + puts_fp(fp, " - "); + print_word(fp, r); + puts_fp(fp, "\n"); + } + if (!BN_mul_word(b.get(), s) || + !BN_add_word(b.get(), r) || + !BN_sub(b.get(), a.get(), b.get())) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Division (word) test failed!\n"); + return false; + } + } + return true; +} + +static bool test_mont(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM A(BN_new()); + ScopedBIGNUM B(BN_new()); + ScopedBIGNUM n(BN_new()); + ScopedBN_MONT_CTX mont(BN_MONT_CTX_new()); + if (!a || !b || !c || !d || !A || !B || !n || !mont) { + return false; + } + + BN_zero(n.get()); + if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) { + fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n"); + return false; + } + ERR_clear_error(); + + if (!BN_set_word(n.get(), 16)) { + return false; + } + if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) { + fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n"); + return false; + } + ERR_clear_error(); + + if (!BN_rand(a.get(), 100, 0, 0) || + !BN_rand(b.get(), 100, 0, 0)) { + return false; + } + + for (int i = 0; i < num2; i++) { + int bits = (200 * (i + 1)) / num2; + + if (bits == 0) { + continue; + } + if (!BN_rand(n.get(), bits, 0, 1) || + !BN_MONT_CTX_set(mont.get(), n.get(), ctx) || + !BN_nnmod(a.get(), a.get(), n.get(), ctx) || + !BN_nnmod(b.get(), b.get(), n.get(), ctx) || + !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) || + !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) || + !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) || + !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, &mont->N); + puts_fp(fp, " - "); + BN_print_fp(fp, A.get()); + puts_fp(fp, "\n"); + } + if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) || + !BN_sub(d.get(), d.get(), A.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Montgomery multiplication test failed!\n"); + return false; + } + } + + return true; +} + +static bool test_mod(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e || + !BN_rand(a.get(), 1024, 0, 0)) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_mod(c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) || + !BN_sub(e.get(), e.get(), c.get())) { + return false; + } + if (!BN_is_zero(e.get())) { + fprintf(stderr, "Modulo test failed!\n"); + return false; + } + } + return true; +} + +static bool test_mod_mul(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get()) || !BN_one(b.get())) { + return false; + } + BN_zero(c.get()); + if (BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) { + fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n"); + return false; + } + ERR_clear_error(); + + for (int j = 0; j < 3; j++) { + if (!BN_rand(c.get(), 1024, 0, 0)) { + return false; + } + for (int i = 0; i < num0; i++) { + if (!BN_rand(a.get(), 475 + i * 10, 0, 0) || + !BN_rand(b.get(), 425 + i * 11, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) { + ERR_print_errors_fp(stderr); + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, c.get()); + if (a->neg != b->neg && !BN_is_zero(e.get())) { + // 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) + puts_fp(fp, " + "); + BN_print_fp(fp, c.get()); + } + puts_fp(fp, " - "); + BN_print_fp(fp, e.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), b.get(), ctx) || + !BN_sub(d.get(), d.get(), e.get()) || + !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Modulo multiply test failed!\n"); + ERR_print_errors_fp(stderr); + return false; + } + } + } + return true; +} + +static bool test_mod_exp(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get()) || !BN_one(b.get())) { + return false; + } + BN_zero(c.get()); + if (BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) { + fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n"); + return 0; + } + ERR_clear_error(); + + if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery + return false; + } + for (int i = 0; i < num2; i++) { + if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || + !BN_rand(b.get(), 2 + i, 0, 0) || + !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) { + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " ^ "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + } + if (!BN_exp(e.get(), a.get(), b.get(), ctx) || + !BN_sub(e.get(), e.get(), d.get()) || + !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + return false; + } + } + + // Regression test for carry propagation bug in sqr8x_reduction. + if (!HexToBIGNUM(&a, "050505050505") || + !HexToBIGNUM(&b, "02") || + !HexToBIGNUM( + &c, + "4141414141414141414141274141414141414141414141414141414141414141" + "4141414141414141414141414141414141414141414141414141414141414141" + "4141414141414141414141800000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000001") || + !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx) || + !BN_mul(e.get(), a.get(), a.get(), ctx)) { + return false; + } + if (BN_cmp(d.get(), e.get()) != 0) { + fprintf(stderr, "BN_mod_exp and BN_mul produce different results!\n"); + return false; + } + + return true; +} + +static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get()) || !BN_one(b.get())) { + return false; + } + BN_zero(c.get()); + if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, + nullptr)) { + fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus succeeded!\n"); + return 0; + } + ERR_clear_error(); + + if (!BN_set_word(c.get(), 16)) { + return false; + } + if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, + nullptr)) { + fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus succeeded!\n"); + return 0; + } + ERR_clear_error(); + + if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery + return false; + } + for (int i = 0; i < num2; i++) { + if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || + !BN_rand(b.get(), 2 + i, 0, 0) || + !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, + NULL)) { + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " ^ "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + } + if (!BN_exp(e.get(), a.get(), b.get(), ctx) || + !BN_sub(e.get(), e.get(), d.get()) || + !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + return false; + } + } + return true; +} + +// Test constant-time modular exponentiation with 1024-bit inputs, +// which on x86_64 cause a different code branch to be taken. +static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM p(BN_new()); + ScopedBIGNUM m(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !p || !m || !d || !e || + !BN_rand(m.get(), 1024, 0, 1) || // must be odd for montgomery + !BN_rand(a.get(), 1024, 0, 0)) { + return false; + } + // Zero exponent. + BN_zero(p.get()); + if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx, + NULL)) { + return false; + } + if (!BN_is_one(d.get())) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + if (!BN_rand(p.get(), 1024, 0, 0)) { + return false; + } + // Zero input. + BN_zero(a.get()); + if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx, + NULL)) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + // 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. + ScopedBN_MONT_CTX mont(BN_MONT_CTX_new()); + if (!mont || !BN_one(a.get()) || + !BN_MONT_CTX_set(mont.get(), m.get(), ctx) || + !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) || + !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx, + NULL) || + !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) { + return false; + } + if (BN_cmp(a.get(), d.get()) != 0) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + // Finally, some regular test vectors. + if (!BN_rand(e.get(), 1024, 0, 0) || + !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx, + NULL) || + !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) { + return false; + } + if (BN_cmp(a.get(), d.get()) != 0) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + + return true; +} + +static bool test_exp(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !d || !e) { + return false; + } + + for (int i = 0; i < num2; i++) { + if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || + !BN_rand(b.get(), 2 + i, 0, 0) || + !BN_exp(d.get(), a.get(), b.get(), ctx)) { + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " ^ "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + } + if (!BN_one(e.get())) { + return false; + } + while (!BN_is_zero(b.get())) { + if (!BN_mul(e.get(), e.get(), a.get(), ctx) || + !BN_sub(b.get(), b.get(), BN_value_one())) { + return false; + } + } + if (!BN_sub(e.get(), e.get(), d.get())) { + return false; + } + if (!BN_is_zero(e.get())) { + fprintf(stderr, "Exponentiation test failed!\n"); + return false; + } + } + return true; +} + +// test_exp_mod_zero tests that 1**0 mod 1 == 0. +static bool test_exp_mod_zero(void) { + ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new()); + if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) { + return false; + } + BN_zero(zero.get()); + + if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) || + !BN_is_zero(r.get()) || + !BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr, + nullptr) || + !BN_is_zero(r.get()) || + !BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(), + nullptr, nullptr) || + !BN_is_zero(r.get()) || + !BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr, + nullptr) || + !BN_is_zero(r.get())) { + return false; + } + + return true; +} + +static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM p(BN_new()); + ScopedBIGNUM r(BN_new()); + if (!a || !p || !r) { + return false; + } + + for (int i = 0; i < 16; i++) { + if (i < 8) { + const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19}; + if (!BN_set_word(p.get(), kPrimes[i])) { + return false; + } + } else { + if (!BN_set_word(a.get(), 32) || + !BN_set_word(r.get(), 2 * i + 1) || + !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), nullptr)) { + return false; + } + } + p->neg = rand_neg(); + + for (int 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.get(), 256, 0, 3) || + !BN_nnmod(r.get(), r.get(), p.get(), ctx) || + !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) || + !BN_rand(a.get(), 256, 0, 3) || + !BN_nnmod(a.get(), a.get(), p.get(), ctx) || + !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) || + !BN_mul(a.get(), a.get(), r.get(), ctx)) { + return false; + } + if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) { + return false; + } + + if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) || + !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) || + !BN_nnmod(a.get(), a.get(), p.get(), ctx)) { + return false; + } + + if (BN_cmp(a.get(), r.get()) != 0) { + fprintf(stderr, "BN_mod_sqrt failed: a = "); + BN_print_fp(stderr, a.get()); + fprintf(stderr, ", r = "); + BN_print_fp(stderr, r.get()); + fprintf(stderr, ", p = "); + BN_print_fp(stderr, p.get()); + fprintf(stderr, "\n"); + return false; + } + } + } + return true; +} + +static bool test_small_prime(FILE *fp, BN_CTX *ctx) { + static const unsigned kBits = 10; + + ScopedBIGNUM r(BN_new()); + if (!r || !BN_generate_prime_ex(r.get(), static_cast(kBits), 0, NULL, + NULL, NULL)) { + return false; + } + if (BN_num_bits(r.get()) != kBits) { + fprintf(fp, "Expected %u bit prime, got %u bit number\n", kBits, + BN_num_bits(r.get())); + return false; + } + + return true; +} + +static bool test_sqrt(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM n(BN_new()); + ScopedBIGNUM nn(BN_new()); + ScopedBIGNUM sqrt(BN_new()); + if (!n || !nn || !sqrt) { + return false; + } + + // Test some random squares. + for (int i = 0; i < 100; i++) { + if (!BN_rand(n.get(), 1024 /* bit length */, + -1 /* no modification of top bits */, + 0 /* don't modify bottom bit */) || + !BN_mul(nn.get(), n.get(), n.get(), ctx) || + !BN_sqrt(sqrt.get(), nn.get(), ctx)) { + ERR_print_errors_fp(stderr); + return false; + } + if (BN_cmp(n.get(), sqrt.get()) != 0) { + fprintf(stderr, "Bad result from BN_sqrt.\n"); + return false; + } + } + + // Test some non-squares. + for (int i = 0; i < 100; i++) { + if (!BN_rand(n.get(), 1024 /* bit length */, + -1 /* no modification of top bits */, + 0 /* don't modify bottom bit */) || + !BN_mul(nn.get(), n.get(), n.get(), ctx) || + !BN_add(nn.get(), nn.get(), BN_value_one())) { + ERR_print_errors_fp(stderr); + return false; + } + + if (BN_sqrt(sqrt.get(), nn.get(), ctx)) { + char *nn_str = BN_bn2dec(nn.get()); + fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str); + OPENSSL_free(nn_str); + } + } + + return true; +} + +static bool test_bn2bin_padded(BN_CTX *ctx) { + uint8_t zeros[256], out[256], reference[128]; + + memset(zeros, 0, sizeof(zeros)); + + // Test edge case at 0. + ScopedBIGNUM n(BN_new()); + if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) { + fprintf(stderr, + "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n"); + return false; + } + memset(out, -1, sizeof(out)); + if (!BN_bn2bin_padded(out, sizeof(out), n.get())) { + fprintf(stderr, + "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n"); + return false; + } + if (memcmp(zeros, out, sizeof(out))) { + fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n"); + return false; + } + + // Test a random numbers at various byte lengths. + for (size_t bytes = 128 - 7; bytes <= 128; bytes++) { + if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */, + 0 /* don't modify bottom bit */)) { + ERR_print_errors_fp(stderr); + return false; + } + if (BN_num_bytes(n.get()) != bytes || + BN_bn2bin(n.get(), reference) != bytes) { + fprintf(stderr, "Bad result from BN_rand; bytes.\n"); + return false; + } + // Empty buffer should fail. + if (BN_bn2bin_padded(NULL, 0, n.get())) { + fprintf(stderr, + "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n"); + return false; + } + // One byte short should fail. + if (BN_bn2bin_padded(out, bytes - 1, n.get())) { + fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n"); + return false; + } + // Exactly right size should encode. + if (!BN_bn2bin_padded(out, bytes, n.get()) || + memcmp(out, reference, bytes) != 0) { + fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); + return false; + } + // Pad up one byte extra. + if (!BN_bn2bin_padded(out, bytes + 1, n.get()) || + memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) { + fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); + return false; + } + // Pad up to 256. + if (!BN_bn2bin_padded(out, sizeof(out), n.get()) || + memcmp(out + sizeof(out) - bytes, reference, bytes) || + memcmp(out, zeros, sizeof(out) - bytes)) { + fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); + return false; + } + } + + return true; +} + +static int DecimalToBIGNUM(ScopedBIGNUM *out, const char *in) { + BIGNUM *raw = NULL; + int ret = BN_dec2bn(&raw, in); + out->reset(raw); + return ret; +} + +static bool test_dec2bn(BN_CTX *ctx) { + ScopedBIGNUM bn; + int ret = DecimalToBIGNUM(&bn, "0"); + if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "256"); + if (ret != 3 || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "-42"); + if (ret != 3 || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "-0"); + if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "42trailing garbage is ignored"); + if (ret != 2 || !BN_abs_is_word(bn.get(), 42) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + return true; +} + +static bool test_hex2bn(BN_CTX *ctx) { + ScopedBIGNUM bn; + int ret = HexToBIGNUM(&bn, "0"); + if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "256"); + if (ret != 3 || !BN_is_word(bn.get(), 0x256) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "-42"); + if (ret != 3 || !BN_abs_is_word(bn.get(), 0x42) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "-0"); + if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored"); + if (ret != 3 || !BN_is_word(bn.get(), 0xabc) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + return true; +} + +static ScopedBIGNUM ASCIIToBIGNUM(const char *in) { + BIGNUM *raw = NULL; + if (!BN_asc2bn(&raw, in)) { + return nullptr; + } + return ScopedBIGNUM(raw); +} + +static bool test_asc2bn(BN_CTX *ctx) { + ScopedBIGNUM bn = ASCIIToBIGNUM("0"); + if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("256"); + if (!bn || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("-42"); + if (!bn || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("0x1234"); + if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("0X1234"); + if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("-0xabcd"); + if (!bn || !BN_abs_is_word(bn.get(), 0xabcd) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("-0"); + if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("123trailing garbage is ignored"); + if (!bn || !BN_is_word(bn.get(), 123) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + return true; +} + +struct MPITest { + const char *base10; + const char *mpi; + size_t mpi_len; +}; + +static const MPITest kMPITests[] = { + { "0", "\x00\x00\x00\x00", 4 }, + { "1", "\x00\x00\x00\x01\x01", 5 }, + { "-1", "\x00\x00\x00\x01\x81", 5 }, + { "128", "\x00\x00\x00\x02\x00\x80", 6 }, + { "256", "\x00\x00\x00\x02\x01\x00", 6 }, + { "-256", "\x00\x00\x00\x02\x81\x00", 6 }, +}; + +static bool test_mpi() { + uint8_t scratch[8]; + + for (size_t i = 0; i < sizeof(kMPITests) / sizeof(kMPITests[0]); i++) { + const MPITest &test = kMPITests[i]; + ScopedBIGNUM bn(ASCIIToBIGNUM(test.base10)); + const size_t mpi_len = BN_bn2mpi(bn.get(), NULL); + if (mpi_len > sizeof(scratch)) { + fprintf(stderr, "MPI test #%u: MPI size is too large to test.\n", + (unsigned)i); + return false; + } + + const size_t mpi_len2 = BN_bn2mpi(bn.get(), scratch); + if (mpi_len != mpi_len2) { + fprintf(stderr, "MPI test #%u: length changes.\n", (unsigned)i); + return false; + } + + if (mpi_len != test.mpi_len || + memcmp(test.mpi, scratch, mpi_len) != 0) { + fprintf(stderr, "MPI test #%u failed:\n", (unsigned)i); + hexdump(stderr, "Expected: ", test.mpi, test.mpi_len); + hexdump(stderr, "Got: ", scratch, mpi_len); + return false; + } + + ScopedBIGNUM bn2(BN_mpi2bn(scratch, mpi_len, NULL)); + if (bn2.get() == nullptr) { + fprintf(stderr, "MPI test #%u: failed to parse\n", (unsigned)i); + return false; + } + + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "MPI test #%u: wrong result\n", (unsigned)i); + return false; + } + } + + return true; +} + +static bool test_rand() { + ScopedBIGNUM bn(BN_new()); + if (!bn) { + return false; + } + + // Test BN_rand accounts for degenerate cases with |top| and |bottom| + // parameters. + if (!BN_rand(bn.get(), 0, 0 /* top */, 0 /* bottom */) || + !BN_is_zero(bn.get())) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + if (!BN_rand(bn.get(), 0, 1 /* top */, 1 /* bottom */) || + !BN_is_zero(bn.get())) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + + if (!BN_rand(bn.get(), 1, 0 /* top */, 0 /* bottom */) || + !BN_is_word(bn.get(), 1)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + if (!BN_rand(bn.get(), 1, 1 /* top */, 0 /* bottom */) || + !BN_is_word(bn.get(), 1)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + if (!BN_rand(bn.get(), 1, -1 /* top */, 1 /* bottom */) || + !BN_is_word(bn.get(), 1)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + + if (!BN_rand(bn.get(), 2, 1 /* top */, 0 /* bottom */) || + !BN_is_word(bn.get(), 3)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + + return true; +} + +struct ASN1Test { + const char *value_ascii; + const char *der; + size_t der_len; +}; + +static const ASN1Test kASN1Tests[] = { + {"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}, + {"0x0102030405060708", + "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10}, + {"0xffffffffffffffff", + "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11}, +}; + +struct ASN1InvalidTest { + const char *der; + size_t der_len; +}; + +static const ASN1InvalidTest kASN1InvalidTests[] = { + // Bad tag. + {"\x03\x01\x00", 3}, + // Empty contents. + {"\x02\x00", 2}, +}; + +// kASN1BuggyTests contains incorrect encodings and the corresponding, expected +// results of |BN_parse_asn1_unsigned_buggy| given that input. +static const ASN1Test kASN1BuggyTests[] = { + // Negative numbers. + {"128", "\x02\x01\x80", 3}, + {"255", "\x02\x01\xff", 3}, + // Unnecessary leading zeros. + {"1", "\x02\x02\x00\x01", 4}, +}; + +static bool test_asn1() { + for (const ASN1Test &test : kASN1Tests) { + ScopedBIGNUM bn = ASCIIToBIGNUM(test.value_ascii); + if (!bn) { + return false; + } + + // Test that the input is correctly parsed. + ScopedBIGNUM bn2(BN_new()); + if (!bn2) { + return false; + } + CBS cbs; + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (!BN_parse_asn1_unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) { + fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n"); + return false; + } + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "Bad parse.\n"); + return false; + } + + // Test the value serializes correctly. + CBB cbb; + uint8_t *der; + size_t der_len; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !BN_marshal_asn1(&cbb, bn.get()) || + !CBB_finish(&cbb, &der, &der_len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes delete_der(der); + if (der_len != test.der_len || + memcmp(der, reinterpret_cast(test.der), der_len) != 0) { + fprintf(stderr, "Bad serialization.\n"); + return false; + } + + // |BN_parse_asn1_unsigned_buggy| parses all valid input. + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (!BN_parse_asn1_unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) { + fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n"); + return false; + } + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "Bad parse.\n"); + return false; + } + } + + for (const ASN1InvalidTest &test : kASN1InvalidTests) { + ScopedBIGNUM bn(BN_new()); + if (!bn) { + return false; + } + CBS cbs; + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (BN_parse_asn1_unsigned(&cbs, bn.get())) { + fprintf(stderr, "Parsed invalid input.\n"); + return false; + } + ERR_clear_error(); + + // All tests in kASN1InvalidTests are also rejected by + // |BN_parse_asn1_unsigned_buggy|. + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (BN_parse_asn1_unsigned_buggy(&cbs, bn.get())) { + fprintf(stderr, "Parsed invalid input.\n"); + return false; + } + ERR_clear_error(); + } + + for (const ASN1Test &test : kASN1BuggyTests) { + // These broken encodings are rejected by |BN_parse_asn1_unsigned|. + ScopedBIGNUM bn(BN_new()); + if (!bn) { + return false; + } + + CBS cbs; + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (BN_parse_asn1_unsigned(&cbs, bn.get())) { + fprintf(stderr, "Parsed invalid input.\n"); + return false; + } + ERR_clear_error(); + + // However |BN_parse_asn1_unsigned_buggy| accepts them. + ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii); + if (!bn2) { + return false; + } + + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (!BN_parse_asn1_unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) { + fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n"); + return false; + } + + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "\"Bad\" parse.\n"); + return false; + } + } + + // Serializing negative numbers is not supported. + ScopedBIGNUM bn = ASCIIToBIGNUM("-1"); + if (!bn) { + return false; + } + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + BN_marshal_asn1(&cbb, bn.get())) { + fprintf(stderr, "Serialized negative number.\n"); + CBB_cleanup(&cbb); + return false; + } + CBB_cleanup(&cbb); + + return true; +} diff --git a/external/boringssl/crypto/bn/cmp.c b/external/boringssl/crypto/bn/cmp.c new file mode 100644 index 0000000000..121c894cdd --- /dev/null +++ b/external/boringssl/crypto/bn/cmp.c @@ -0,0 +1,214 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "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; +} + +int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) { + if (a->top != b->top) { + return 0; + } + + int limbs_are_equal = + CRYPTO_memcmp(a->d, b->d, (size_t)a->top * sizeof(a->d[0])) == 0; + + return constant_time_select_int(constant_time_eq_int(a->neg, b->neg), + limbs_are_equal, 0); +} diff --git a/external/boringssl/crypto/bn/convert.c b/external/boringssl/crypto/bn/convert.c new file mode 100644 index 0000000000..9125bf84be --- /dev/null +++ b/external/boringssl/crypto/bn/convert.c @@ -0,0 +1,607 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + +BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) { + size_t num_words; + unsigned 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; + } + + /* |bn_wexpand| must check bounds on |num_words| to write it into + * |ret->dmax|. */ + assert(num_words <= INT_MAX); + ret->top = (int)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; +} + +int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) { + uint8_t *ptr; + return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in); +} + +static const char hextable[] = "0123456789abcdef"; + +char *BN_bn2hex(const BIGNUM *bn) { + int i, j, v, z = 0; + char *buf; + char *p; + + buf = OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2); + if (buf == NULL) { + OPENSSL_PUT_ERROR(BN, 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 |in_len| bytes of hex data from |in| and updates |bn|. */ +static int decode_hex(BIGNUM *bn, const char *in, int in_len) { + if (in_len > INT_MAX/4) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return 0; + } + /* |in_len| is the number of hex digits. */ + if (bn_expand(bn, in_len * 4) == NULL) { + return 0; + } + + int i = 0; + while (in_len > 0) { + /* Decode one |BN_ULONG| at a time. */ + int todo = BN_BYTES * 2; + if (todo > in_len) { + todo = in_len; + } + + BN_ULONG word = 0; + int j; + for (j = todo; j > 0; j--) { + char c = in[in_len - j]; + + BN_ULONG hex; + if (c >= '0' && c <= '9') { + hex = c - '0'; + } else if (c >= 'a' && c <= 'f') { + hex = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + hex = c - 'A' + 10; + } else { + hex = 0; + /* This shouldn't happen. The caller checks |isxdigit|. */ + assert(0); + } + word = (word << 4) | hex; + } + + bn->d[i++] = word; + in_len -= todo; + } + assert(i <= bn->dmax); + bn->top = i; + return 1; +} + +/* decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|. */ +static int decode_dec(BIGNUM *bn, const char *in, int in_len) { + int i, j; + BN_ULONG l = 0; + + /* Decode |BN_DEC_NUM| digits at a time. */ + j = BN_DEC_NUM - (in_len % BN_DEC_NUM); + if (j == BN_DEC_NUM) { + j = 0; + } + l = 0; + for (i = 0; i < in_len; i++) { + l *= 10; + l += in[i] - '0'; + if (++j == BN_DEC_NUM) { + if (!BN_mul_word(bn, BN_DEC_CONV) || + !BN_add_word(bn, l)) { + return 0; + } + l = 0; + j = 0; + } + } + return 1; +} + +typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len); +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 + neg < INT_MAX; 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); + } + + if (!decode(ret, in, i)) { + goto err; + } + + bn_correct_top(ret); + if (!BN_is_zero(ret)) { + ret->neg = neg; + } + + *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 = OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG)); + buf = OPENSSL_malloc(num + 3); + if ((buf == NULL) || (bn_data == NULL)) { + OPENSSL_PUT_ERROR(BN, 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: + OPENSSL_free(bn_data); + BN_free(t); + if (!ok) { + 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 == '-' && !BN_is_zero(*outp)) { + (*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; + } +} + +size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) { + const size_t bits = BN_num_bits(in); + const size_t bytes = (bits + 7) / 8; + /* If the number of bits is a multiple of 8, i.e. if the MSB is set, + * prefix with a zero byte. */ + int extend = 0; + if (bytes != 0 && (bits & 0x07) == 0) { + extend = 1; + } + + const size_t len = bytes + extend; + if (len < bytes || + 4 + len < len || + (len & 0xffffffff) != len) { + /* If we cannot represent the number then we emit zero as the interface + * doesn't allow an error to be signalled. */ + if (out) { + memset(out, 0, 4); + } + return 4; + } + + if (out == NULL) { + return 4 + len; + } + + out[0] = len >> 24; + out[1] = len >> 16; + out[2] = len >> 8; + out[3] = len; + if (extend) { + out[4] = 0; + } + BN_bn2bin(in, out + 4 + extend); + if (in->neg && len > 0) { + out[4] |= 0x80; + } + return len + 4; +} + +BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) { + if (len < 4) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return NULL; + } + const size_t in_len = ((size_t)in[0] << 24) | + ((size_t)in[1] << 16) | + ((size_t)in[2] << 8) | + ((size_t)in[3]); + if (in_len != len - 4) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return NULL; + } + + int out_is_alloced = 0; + if (out == NULL) { + out = BN_new(); + if (out == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + return NULL; + } + out_is_alloced = 1; + } + + if (in_len == 0) { + BN_zero(out); + return out; + } + + in += 4; + if (BN_bin2bn(in, in_len, out) == NULL) { + if (out_is_alloced) { + BN_free(out); + } + return NULL; + } + out->neg = ((*in) & 0x80) != 0; + if (out->neg) { + BN_clear_bit(out, BN_num_bits(out) - 1); + } + return out; +} diff --git a/external/boringssl/crypto/bn/ctx.c b/external/boringssl/crypto/bn/ctx.c new file mode 100644 index 0000000000..48d9adf651 --- /dev/null +++ b/external/boringssl/crypto/bn/ctx.c @@ -0,0 +1,311 @@ +/* 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 + +#include + +#include +#include + + +/* 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, 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_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_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) { + 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)); + } + 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/external/boringssl/crypto/bn/div.c b/external/boringssl/crypto/bn/div.c new file mode 100644 index 0000000000..e824458baf --- /dev/null +++ b/external/boringssl/crypto/bn/div.c @@ -0,0 +1,671 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include "internal.h" + + +#if !defined(BN_ULLONG) +/* bn_div_words divides a double-width |h|,|l| by |d| and returns the result, + * which must fit in a |BN_ULONG|. */ +static 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_ULLONG) */ + +static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out, + BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) { + /* GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when + * the |BN_ULLONG|-based C code is used. + * + * GCC bugs: + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668 + * + * Clang bugs: + * * https://llvm.org/bugs/show_bug.cgi?id=6397 + * * https://llvm.org/bugs/show_bug.cgi?id=12418 + * + * These issues aren't specific to x86 and x86_64, so it might be worthwhile + * to add more assembly language implementations. */ +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__) + __asm__ volatile ( + "divl %4" + : "=a"(*quotient_out), "=d"(*rem_out) + : "a"(n1), "d"(n0), "g"(d0) + : "cc" ); +#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__) + __asm__ volatile ( + "divq %4" + : "=a"(*quotient_out), "=d"(*rem_out) + : "a"(n1), "d"(n0), "g"(d0) + : "cc" ); +#else +#if defined(BN_ULLONG) + BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1; + *quotient_out = (BN_ULONG)(n / d0); +#else + *quotient_out = bn_div_words(n0, n1, d0); +#endif + *rem_out = n1 - (*quotient_out * d0); +#endif +} + +/* 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_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_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 */ + bn_div_rem_words(&q, &rem, n0, n1, d0); + +#ifdef BN_ULLONG + BN_ULLONG 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_ULLONG */ + BN_ULONG t2l, t2h; + BN_UMULT_LOHI(t2l, t2h, d1, q); + 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_ULLONG */ + } + + 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; + if (!BN_rshift(rm, snum, norm_shift)) { + goto err; + } + 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)); + + 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_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 for |bn_div_rem_words|. */ + 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 = a->d[i]; + BN_ULONG d; + BN_ULONG unused_rem; + bn_div_rem_words(&d, &unused_rem, 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_ULLONG + BN_ULONG ret = 0; +#else + BN_ULLONG ret = 0; +#endif + int i; + + if (w == 0) { + return (BN_ULONG) -1; + } + +#ifndef BN_ULLONG + /* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back + * to using |BN_div_word|. */ + if (w > ((BN_ULONG)1 << BN_BITS4)) { + BIGNUM *tmp = BN_dup(a); + if (tmp == NULL) { + return (BN_ULONG)-1; + } + ret = BN_div_word(tmp, w); + BN_free(tmp); + return ret; + } +#endif + + w &= BN_MASK2; + for (i = a->top - 1; i >= 0; i--) { +#ifndef BN_ULLONG + 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/external/boringssl/crypto/bn/exponentiation.c b/external/boringssl/crypto/bn/exponentiation.c new file mode 100644 index 0000000000..eedc88e879 --- /dev/null +++ b/external/boringssl/crypto/bn/exponentiation.c @@ -0,0 +1,1258 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + +#include "internal.h" + + +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) +#define OPENSSL_BN_ASM_MONT5 +#define RSAZ_ENABLED + +#include "rsaz_exp.h" + +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); +#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, 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; + } + } + } + + if (r != rr && !BN_copy(r, rr)) { + goto err; + } + ret = 1; + +err: + 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->shift = 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)) { + goto err; + } + 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_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, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bits = BN_num_bits(p); + + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + BN_zero(r); + return 1; + } + return BN_one(r); + } + + 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) { + if (BN_is_odd(m)) { + 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, const BN_MONT_CTX *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 *new_mont = NULL; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { + return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, mont); + } + + if (!BN_is_odd(m)) { + OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + BN_zero(rr); + return 1; + } + return BN_one(rr); + } + + 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; + } + + /* Allocate a montgomery context if it was not supplied by the caller. */ + if (mont == NULL) { + new_mont = BN_MONT_CTX_new(); + if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + goto err; + } + mont = new_mont; + } + + 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 && !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: + BN_MONT_CTX_free(new_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 window) { + int i, j; + const int width = 1 << window; + BN_ULONG *table = (BN_ULONG *) buf; + + if (top > b->top) { + top = b->top; /* this works because 'buf' is explicitly zeroed */ + } + + for (i = 0, j = idx; i < top; i++, j += width) { + table[j] = b->d[i]; + } + + return 1; +} + +static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx, + int window) { + int i, j; + const int width = 1 << window; + volatile BN_ULONG *table = (volatile BN_ULONG *)buf; + + if (bn_wexpand(b, top) == NULL) { + return 0; + } + + if (window <= 3) { + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < width; j++) { + acc |= table[j] & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + } + + b->d[i] = acc; + } + } else { + int xstride = 1 << (window - 2); + BN_ULONG y0, y1, y2, y3; + + i = idx >> (window - 2); /* equivalent of idx / xstride */ + idx &= xstride - 1; /* equivalent of idx % xstride */ + + y0 = (BN_ULONG)0 - (constant_time_eq_int(i, 0) & 1); + y1 = (BN_ULONG)0 - (constant_time_eq_int(i, 1) & 1); + y2 = (BN_ULONG)0 - (constant_time_eq_int(i, 2) & 1); + y3 = (BN_ULONG)0 - (constant_time_eq_int(i, 3) & 1); + + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < xstride; j++) { + acc |= ((table[j + 0 * xstride] & y0) | (table[j + 1 * xstride] & y1) | + (table[j + 2 * xstride] & y2) | (table[j + 3 * xstride] & y3)) & + ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + } + + b->d[i] = acc; + } + } + + b->top = top; + bn_correct_top(b); + return 1; +} + +/* 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, + const BN_MONT_CTX *mont) { + int i, bits, ret = 0, window, wvalue; + int top; + BN_MONT_CTX *new_mont = NULL; + + int numPowers; + unsigned char *powerbufFree = NULL; + int powerbufLen = 0; + unsigned char *powerbuf = NULL; + BIGNUM tmp, am; + + if (!BN_is_odd(m)) { + OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + + top = m->top; + + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + BN_zero(rr); + return 1; + } + return BN_one(rr); + } + + /* Allocate a montgomery context if it was not supplied by the caller. */ + if (mont == NULL) { + new_mont = BN_MONT_CTX_new(); + if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + goto err; + } + mont = new_mont; + } + +#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 */ + /* reserve space for mont->N.d[] copy */ + powerbufLen += top * sizeof(mont->N.d[0]); + } +#endif + + /* Allocate a buffer large enough to hold all of the pre-computed + * powers of am, am itself and tmp. + */ + numPowers = 1 << window; + powerbufLen += + sizeof(m->d[0]) * + (top * numPowers + ((2 * top) > numPowers ? (2 * top) : numPowers)); +#ifdef alloca + if (powerbufLen < 3072) { + powerbufFree = alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH); + } else +#endif + { + if ((powerbufFree = 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) || + !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) { + const BN_ULONG *n0 = mont->n0; + BN_ULONG *np; + + /* 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; + } + + /* copy mont->N.d[] to improve cache locality */ + for (np = am.d + top, i = 0; i < top; i++) { + np[i] = mont->N.d[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, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + for (j = 2 * i; j < 32; j *= 2) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, j); + } + } + for (; i < 16; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, 2 * i); + } + for (; i < 32; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + } + + 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, np, 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, np, n0, top, wvalue); + } + } + + ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, 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, window) || + !copy_to_prebuf(&am, top, powerbuf, 1, window)) { + goto err; + } + + /* If the window size is greater than 1, then calculate + * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1) + * (even powers could instead be computed as (a^(i/2))^2 + * to use the slight performance advantage of sqr over mul). + */ + if (window > 1) { + if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) || + !copy_to_prebuf(&tmp, top, powerbuf, 2, window)) { + goto err; + } + for (i = 3; i < numPowers; i++) { + /* Calculate a^i = a^(i-1) * a */ + if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) || + !copy_to_prebuf(&tmp, top, powerbuf, i, window)) { + goto err; + } + } + } + + bits--; + for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) { + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + } + if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, window)) { + goto err; + } + + /* Scan the exponent one window at a time starting from the most + * significant bits. + */ + while (bits >= 0) { + wvalue = 0; /* The 'value' of the window */ + + /* Scan the window, squaring the result as we go */ + for (i = 0; i < window; i++, bits--) { + if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx)) { + goto err; + } + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + } + + /* Fetch the appropriate pre-computed value from the pre-buf */ + if (!copy_from_prebuf(&am, top, powerbuf, wvalue, window)) { + goto err; + } + + /* Multiply the result into the intermediate result */ + if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx)) { + goto err; + } + } + } + + /* Convert the final result from montgomery to standard format */ + if (!BN_from_montgomery(rr, &tmp, mont, ctx)) { + goto err; + } + ret = 1; + +err: + BN_MONT_CTX_free(new_mont); + if (powerbuf != NULL) { + OPENSSL_cleanse(powerbuf, powerbufLen); + OPENSSL_free(powerbufFree); + } + return (ret); +} + +int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont) { + BIGNUM a_bignum; + BN_init(&a_bignum); + + int ret = 0; + + if (!BN_set_word(&a_bignum, a)) { + OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = BN_mod_exp_mont(rr, &a_bignum, p, m, ctx, mont); + +err: + BN_free(&a_bignum); + + 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, const BN_MONT_CTX *mont) { + BIGNUM tmp; + BN_init(&tmp); + + int ret = 0; + BN_MONT_CTX *new_mont = NULL; + + /* Allocate a montgomery context if it was not supplied by the caller. */ + if (mont == NULL) { + new_mont = BN_MONT_CTX_new(); + if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + goto err; + } + mont = new_mont; + } + + /* BN_mod_mul_montgomery removes one Montgomery factor, so passing one + * Montgomery-encoded and one non-Montgomery-encoded value gives a + * non-Montgomery-encoded result. */ + if (!BN_mod_exp_mont(rr, a1, p1, m, ctx, mont) || + !BN_mod_exp_mont(&tmp, a2, p2, m, ctx, mont) || + !BN_to_montgomery(rr, rr, mont, ctx) || + !BN_mod_mul_montgomery(rr, rr, &tmp, mont, ctx)) { + goto err; + } + + ret = 1; + +err: + BN_MONT_CTX_free(new_mont); + BN_free(&tmp); + + return ret; +} diff --git a/external/boringssl/crypto/bn/gcd.c b/external/boringssl/crypto/bn/gcd.c new file mode 100644 index 0000000000..c9a7123f23 --- /dev/null +++ b/external/boringssl/crypto/bn/gcd.c @@ -0,0 +1,712 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include "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, int *out_no_inverse, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx); + +BIGNUM *BN_mod_inverse_ex(BIGNUM *out, int *out_no_inverse, 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, out_no_inverse, a, n, ctx); + } + + *out_no_inverse = 0; + + 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_zero(Y); + if (!BN_one(X) || BN_copy(B, a) == NULL || 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_BITS2 <= 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 { + *out_no_inverse = 1; + OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); + goto err; + } + ret = R; + +err: + if (ret == NULL && out == NULL) { + BN_free(R); + } + BN_CTX_end(ctx); + return ret; +} + +BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx) { + int no_inverse; + return BN_mod_inverse_ex(out, &no_inverse, a, n, ctx); +} + +/* 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, int *out_no_inverse, + 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; + + *out_no_inverse = 0; + + 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_zero(Y); + if (!BN_one(X) || BN_copy(B, a) == NULL || 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; + } + + if (!BN_is_one(A)) { + *out_no_inverse = 1; + OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); + goto err; + } + + /* + * 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|). */ + + /* 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; + } + } + + ret = R; + +err: + if (ret == NULL && out == NULL) { + BN_free(R); + } + + BN_CTX_end(ctx); + return ret; +} diff --git a/external/boringssl/crypto/bn/generic.c b/external/boringssl/crypto/bn/generic.c new file mode 100644 index 0000000000..f552d99f89 --- /dev/null +++ b/external/boringssl/crypto/bn/generic.c @@ -0,0 +1,703 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "internal.h" + + +/* This file has two other implementations: x86 assembly language in + * asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. */ +#if defined(OPENSSL_NO_ASM) || \ + !(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__))) + +#ifdef BN_ULLONG +#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); \ + } + +#else + +#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); \ + } + +#endif /* !BN_ULLONG */ + +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--; + } +} + +#ifdef BN_ULLONG +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_ULLONG */ + +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_ULLONG */ + +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_ULLONG + +/* 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) + +#else + +/* 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) + +#endif /* !BN_ULLONG */ + +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 diff --git a/external/boringssl/crypto/bn/internal.h b/external/boringssl/crypto/bn/internal.h new file mode 100644 index 0000000000..8b1c8660fd --- /dev/null +++ b/external/boringssl/crypto/bn/internal.h @@ -0,0 +1,237 @@ +/* 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 + +#if defined(OPENSSL_X86_64) && defined(_MSC_VER) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#pragma intrinsic(__umulh, _umul128) +#endif + +#include "../internal.h" + +#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, size_t bits); + +#if defined(OPENSSL_64_BIT) + +#if !defined(_MSC_VER) +/* MSVC doesn't support two-word integers on 64-bit. */ +#define BN_ULLONG uint128_t +#endif + +#define BN_BITS2 64 +#define BN_BYTES 8 +#define BN_BITS4 32 +#define BN_MASK2 (0xffffffffffffffffUL) +#define BN_MASK2l (0xffffffffUL) +#define BN_MASK2h (0xffffffff00000000UL) +#define BN_MASK2h1 (0xffffffff80000000UL) +#define BN_TBIT (0x8000000000000000UL) +#define BN_DEC_CONV (10000000000000000000UL) +#define BN_DEC_NUM 19 +#define TOBN(hi, lo) ((BN_ULONG)hi << 32 | lo) + +#elif defined(OPENSSL_32_BIT) + +#define BN_ULLONG uint64_t +#define BN_BITS2 32 +#define BN_BYTES 4 +#define BN_BITS4 16 +#define BN_MASK2 (0xffffffffUL) +#define BN_MASK2l (0xffffUL) +#define BN_MASK2h1 (0xffff8000UL) +#define BN_MASK2h (0xffff0000UL) +#define BN_TBIT (0x80000000UL) +#define BN_DEC_CONV (1000000000UL) +#define BN_DEC_NUM 9 +#define TOBN(hi, lo) lo, hi + +#else +#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +#endif + + +#define STATIC_BIGNUM(x) \ + { \ + (BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG), \ + sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \ + } + +#if defined(BN_ULLONG) +#define Lw(t) (((BN_ULONG)(t))&BN_MASK2) +#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) +#endif + + +/* bn_set_words sets |bn| to the value encoded in the |num| words in |words|, + * least significant word first. */ +int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num); + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); +BN_ULONG bn_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(OPENSSL_X86_64) && defined(_MSC_VER) +#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high))) +#endif + +#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI) +#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform." +#endif + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BN_INTERNAL_H */ diff --git a/external/boringssl/crypto/bn/kronecker.c b/external/boringssl/crypto/bn/kronecker.c new file mode 100644 index 0000000000..23ef79afa5 --- /dev/null +++ b/external/boringssl/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 + +#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/external/boringssl/crypto/bn/montgomery.c b/external/boringssl/crypto/bn/montgomery.c new file mode 100644 index 0000000000..7c3b420cb8 --- /dev/null +++ b/external/boringssl/crypto/bn/montgomery.c @@ -0,0 +1,480 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +#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; + } + + memset(ret, 0, sizeof(BN_MONT_CTX)); + BN_init(&ret->RR); + BN_init(&ret->N); + + return ret; +} + +void BN_MONT_CTX_free(BN_MONT_CTX *mont) { + if (mont == NULL) { + return; + } + + BN_free(&mont->RR); + BN_free(&mont->N); + OPENSSL_free(mont); +} + +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from) { + if (to == from) { + return to; + } + + if (!BN_copy(&to->RR, &from->RR) || + !BN_copy(&to->N, &from->N)) { + return NULL; + } + 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]; + + if (BN_is_zero(mod)) { + OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); + return 0; + } + + 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; + +#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 + + /* RR = (2^ri)^2 == 2^(ri*2) == 1 << (ri*2), which has its (ri*2)th bit set. */ + int ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; + BN_zero(&(mont->RR)); + if (!BN_set_bit(&(mont->RR), 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; +} + +int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock, + const BIGNUM *mod, BN_CTX *bn_ctx) { + CRYPTO_MUTEX_lock_read(lock); + BN_MONT_CTX *ctx = *pmont; + CRYPTO_MUTEX_unlock_read(lock); + + if (ctx) { + return 1; + } + + CRYPTO_MUTEX_lock_write(lock); + ctx = *pmont; + if (ctx) { + goto out; + } + + ctx = BN_MONT_CTX_new(); + if (ctx == NULL) { + goto out; + } + if (!BN_MONT_CTX_set(ctx, mod, bn_ctx)) { + BN_MONT_CTX_free(ctx); + ctx = NULL; + goto out; + } + *pmont = ctx; + +out: + CRYPTO_MUTEX_unlock_write(lock); + return ctx != NULL; +} + +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); +} + +static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, + const BN_MONT_CTX *mont) { + BN_ULONG *ap, *np, *rp, n0, v, carry; + int nl, max, i; + + const BIGNUM *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; + uintptr_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 = (0u - (uintptr_t)v); + nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_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; +} + +int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont, + BN_CTX *ctx) { + int ret = 0; + BIGNUM *t; + + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if (t == NULL || + !BN_copy(t, a)) { + goto err; + } + + ret = BN_from_montgomery_word(r, t, mont); + +err: + BN_CTX_end(ctx); + + return ret; +} + +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/external/boringssl/crypto/bn/mul.c b/external/boringssl/crypto/bn/mul.c new file mode 100644 index 0000000000..06e53ee0e6 --- /dev/null +++ b/external/boringssl/crypto/bn/mul.c @@ -0,0 +1,869 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include "internal.h" + + +#define BN_MUL_RECURSIVE_SIZE_NORMAL 16 +#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL + + +static 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; + } +} + +#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; + } + } + + static const int kMulNormalSize = 16; + if (al >= kMulNormalSize && bl >= kMulNormalSize) { + 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)) { + goto err; + } + 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)) { + goto err; + } + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} diff --git a/external/boringssl/crypto/bn/prime.c b/external/boringssl/crypto/bn/prime.c new file mode 100644 index 0000000000..d07e6094b9 --- /dev/null +++ b/external/boringssl/crypto/bn/prime.c @@ -0,0 +1,845 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include "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_R_BITS_TOO_SMALL); + return 0; + } else if (bits == 2 && safe) { + /* The smallest safe prime (7) is three bits. */ + OPENSSL_PUT_ERROR(BN, 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 = BN_CTX_get(ctx); + if (t == NULL || !BN_copy(t, a)) { + goto err; + } + 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; + if (bits == BN_BITS2) { + /* Avoid undefined behavior. */ + size_limit = ~((BN_ULONG)0) - get_word(rnd); + } else { + 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) != (unsigned)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/external/boringssl/crypto/bn/random.c b/external/boringssl/crypto/bn/random.c new file mode 100644 index 0000000000..3116e54731 --- /dev/null +++ b/external/boringssl/crypto/bn/random.c @@ -0,0 +1,326 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include + +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, 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 && bits > 1) { + 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_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_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_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_R_DIV_BY_ZERO); + goto err; + } + + k_bytes = OPENSSL_malloc(num_k_bytes); + if (!k_bytes) { + OPENSSL_PUT_ERROR(BN, 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_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: + OPENSSL_free(k_bytes); + return ret; +} diff --git a/external/boringssl/crypto/bn/rsaz_exp.c b/external/boringssl/crypto/bn/rsaz_exp.c new file mode 100644 index 0000000000..30f08e5f8b --- /dev/null +++ b/external/boringssl/crypto/bn/rsaz_exp.c @@ -0,0 +1,319 @@ +/***************************************************************************** +* * +* 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 + +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) + +#include "rsaz_exp.h" + +#include + +#include "../internal.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); + +alignas(64) 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}; +alignas(64) 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) +{ + alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */ + unsigned char *a_inv, *m, *result, + *table_s = storage + (320 * 3), + *R2 = table_s; /* borrow */ + int index; + int wvalue; + + if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) { + result = storage; + a_inv = storage + 320; + m = storage + (320 * 2); /* should not cross page */ + } else { + m = storage; /* should not cross page */ + result = storage + 320; + a_inv = storage + (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 + + const uint8_t *p_str = (const uint8_t *)exponent; + + /* load first window */ + 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 = *((const 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]) +{ + alignas(64) uint8_t storage[(16*8*8) + (64 * 2)]; /* 1.2KB */ + unsigned char *table = storage; + BN_ULONG *a_inv = (BN_ULONG *)(table+16*8*8), + *temp = (BN_ULONG *)(table+16*8*8+8*8); + 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); + + const uint8_t *p_str = (const uint8_t *)exponent; + + /* 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/external/boringssl/crypto/bn/rsaz_exp.h b/external/boringssl/crypto/bn/rsaz_exp.h new file mode 100644 index 0000000000..c752b45f21 --- /dev/null +++ b/external/boringssl/crypto/bn/rsaz_exp.h @@ -0,0 +1,56 @@ +/***************************************************************************** +* * +* 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 * +*****************************************************************************/ + +#ifndef RSAZ_EXP_H +#define RSAZ_EXP_H + +#include + +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/external/boringssl/crypto/bn/shift.c b/external/boringssl/crypto/bn/shift.c new file mode 100644 index 0000000000..defec92918 --- /dev/null +++ b/external/boringssl/crypto/bn/shift.c @@ -0,0 +1,299 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + +#include "internal.h" + + +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) { + int i, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l; + + if (n < 0) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + 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; + + if (n < 0) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + 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/external/boringssl/crypto/bn/sqrt.c b/external/boringssl/crypto/bn/sqrt.c new file mode 100644 index 0000000000..2ed66c22c7 --- /dev/null +++ b/external/boringssl/crypto/bn/sqrt.c @@ -0,0 +1,505 @@ +/* Written by Lenka Fibikova + * 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 + +#include + + +/* 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_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, + * , + * 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_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_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_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_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_R_NOT_A_SQUARE); + err = 1; + } + } + +end: + if (err) { + if (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_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, 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, 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_R_NOT_A_SQUARE); + goto err; + } + + ok = 1; + +err: + if (ok && out_sqrt == in && !BN_copy(out_sqrt, estimate)) { + ok = 0; + } + BN_CTX_end(ctx); + return ok; +} diff --git a/external/boringssl/crypto/buf/CMakeLists.txt b/external/boringssl/crypto/buf/CMakeLists.txt new file mode 100644 index 0000000000..63f10255b0 --- /dev/null +++ b/external/boringssl/crypto/buf/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + buf + + OBJECT + + buf.c +) diff --git a/external/boringssl/crypto/buf/buf.c b/external/boringssl/crypto/buf/buf.c new file mode 100644 index 0000000000..efe9952af5 --- /dev/null +++ b/external/boringssl/crypto/buf/buf.c @@ -0,0 +1,239 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + + +BUF_MEM *BUF_MEM_new(void) { + BUF_MEM *ret; + + ret = OPENSSL_malloc(sizeof(BUF_MEM)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BUF, 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 int buf_mem_reserve(BUF_MEM *buf, size_t cap, int clean) { + if (buf->max >= cap) { + return 1; + } + + size_t n = cap + 3; + if (n < cap) { + /* overflow */ + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return 0; + } + n = n / 3; + size_t alloc_size = n * 4; + if (alloc_size / 4 != n) { + /* overflow */ + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return 0; + } + + char *new_buf; + 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, ERR_R_MALLOC_FAILURE); + return 0; + } + + buf->data = new_buf; + buf->max = alloc_size; + return 1; +} + +int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) { + return buf_mem_reserve(buf, cap, 0 /* don't clear old buffer contents. */); +} + +static size_t buf_mem_grow(BUF_MEM *buf, size_t len, int clean) { + if (!buf_mem_reserve(buf, len, clean)) { + return 0; + } + if (buf->length < len) { + 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, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret = OPENSSL_malloc(alloc_size); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BUF, 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 (dst_size == 0) { + return NULL; + } + + ret = OPENSSL_malloc(dst_size); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(ret, data, dst_size); + return ret; +} diff --git a/external/boringssl/crypto/bytestring/CMakeLists.txt b/external/boringssl/crypto/bytestring/CMakeLists.txt new file mode 100644 index 0000000000..a1964b2eb7 --- /dev/null +++ b/external/boringssl/crypto/bytestring/CMakeLists.txt @@ -0,0 +1,25 @@ +include_directories(../../include) + +add_library( + bytestring + + OBJECT + + asn1_compat.c + ber.c + cbs.c + cbb.c +) + +if(ENABLE_TESTS) +add_executable( + bytestring_test + + bytestring_test.cc + + $ +) + +target_link_libraries(bytestring_test crypto) +add_dependencies(all_tests bytestring_test) +endif() diff --git a/external/boringssl/crypto/bytestring/asn1_compat.c b/external/boringssl/crypto/bytestring/asn1_compat.c new file mode 100644 index 0000000000..b17d2d1219 --- /dev/null +++ b/external/boringssl/crypto/bytestring/asn1_compat.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + +#include + +#include +#include +#include + +#include + +#include "internal.h" + + +int CBB_finish_i2d(CBB *cbb, uint8_t **outp) { + assert(cbb->base->can_resize); + + uint8_t *der; + size_t der_len; + if (!CBB_finish(cbb, &der, &der_len)) { + CBB_cleanup(cbb); + return -1; + } + if (der_len > INT_MAX) { + OPENSSL_free(der); + return -1; + } + if (outp != NULL) { + if (*outp == NULL) { + *outp = der; + der = NULL; + } else { + memcpy(*outp, der, der_len); + *outp += der_len; + } + } + OPENSSL_free(der); + return (int)der_len; +} diff --git a/external/boringssl/crypto/bytestring/ber.c b/external/boringssl/crypto/bytestring/ber.c new file mode 100644 index 0000000000..04fcac6aa3 --- /dev/null +++ b/external/boringssl/crypto/bytestring/ber.c @@ -0,0 +1,263 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include "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; + +/* is_string_type returns one if |tag| is a string type and zero otherwise. It + * ignores the constructed bit. */ +static int is_string_type(unsigned tag) { + if ((tag & 0xc0) != 0) { + return 0; + } + switch (tag & 0x1f) { + case CBS_ASN1_BITSTRING: + case CBS_ASN1_OCTETSTRING: + case CBS_ASN1_UTF8STRING: + case CBS_ASN1_NUMERICSTRING: + case CBS_ASN1_PRINTABLESTRING: + case CBS_ASN1_T16STRING: + case CBS_ASN1_VIDEOTEXSTRING: + case CBS_ASN1_IA5STRING: + case CBS_ASN1_GRAPHICSTRING: + case CBS_ASN1_VISIBLESTRING: + case CBS_ASN1_GENERALSTRING: + case CBS_ASN1_UNIVERSALSTRING: + case CBS_ASN1_BMPSTRING: + return 1; + default: + return 0; + } +} + +/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found| + * depending on whether an indefinite length element or constructed string was + * found. The value of |orig_in| is not changed. It returns one on success (i.e. + * |*ber_found| was set) and zero on error. */ +static int cbs_find_ber(const 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_ber_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) { + /* Found an indefinite-length element. */ + *ber_found = 1; + return 1; + } + if (tag & CBS_ASN1_CONSTRUCTED) { + if (is_string_type(tag)) { + /* Constructed strings are only legal in BER and require conversion. */ + *ber_found = 1; + return 1; + } + if (!CBS_skip(&contents, header_len) || + !cbs_find_ber(&contents, ber_found, depth + 1)) { + return 0; + } + } + } + + return 1; +} + +/* is_eoc returns true if |header_len| and |contents|, as returned by + * |CBS_get_any_ber_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 + * |string_tag| is non-zero, then all elements must match |string_tag| up to the + * constructed bit and primitive element bodies are written to |out| without + * element headers. This is used when concatenating the fragments of a + * constructed string. 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, unsigned string_tag, + char looking_for_eoc, unsigned depth) { + assert(!(string_tag & CBS_ASN1_CONSTRUCTED)); + + if (depth > kMaxDepth) { + return 0; + } + + while (CBS_len(in) > 0) { + CBS contents; + unsigned tag, child_string_tag = string_tag; + size_t header_len; + CBB *out_contents, out_contents_storage; + + if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) { + return 0; + } + + if (is_eoc(header_len, &contents)) { + return looking_for_eoc; + } + + if (string_tag != 0) { + /* This is part of a constructed string. All elements must match + * |string_tag| up to the constructed bit and get appended to |out| + * without a child element. */ + if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) { + return 0; + } + out_contents = out; + } else { + unsigned out_tag = tag; + if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) { + /* If a constructed string, clear the constructed bit and inform + * children to concatenate bodies. */ + out_tag &= ~CBS_ASN1_CONSTRUCTED; + child_string_tag = out_tag; + } + if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) { + return 0; + } + out_contents = &out_contents_storage; + } + + if (CBS_len(&contents) == header_len && header_len > 0 && + CBS_data(&contents)[header_len - 1] == 0x80) { + /* This is an indefinite length element. */ + if (!cbs_convert_ber(in, out_contents, child_string_tag, + 1 /* looking for eoc */, depth + 1) || + !CBB_flush(out)) { + return 0; + } + continue; + } + + if (!CBS_skip(&contents, header_len)) { + return 0; + } + + if (tag & CBS_ASN1_CONSTRUCTED) { + /* Recurse into children. */ + if (!cbs_convert_ber(&contents, out_contents, child_string_tag, + 0 /* not looking for eoc */, depth + 1)) { + return 0; + } + } else { + /* Copy primitive contents as-is. */ + if (!CBB_add_bytes(out_contents, CBS_data(&contents), + CBS_len(&contents))) { + return 0; + } + } + + if (!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; + } + + if (!CBB_init(&cbb, CBS_len(in)) || + !cbs_convert_ber(in, &cbb, 0, 0, 0) || + !CBB_finish(&cbb, out, out_len)) { + CBB_cleanup(&cbb); + return 0; + } + + return 1; +} + +int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage, + unsigned outer_tag, unsigned inner_tag) { + assert(!(outer_tag & CBS_ASN1_CONSTRUCTED)); + assert(!(inner_tag & CBS_ASN1_CONSTRUCTED)); + assert(is_string_type(inner_tag)); + + if (CBS_peek_asn1_tag(in, outer_tag)) { + /* Normal implicitly-tagged string. */ + *out_storage = NULL; + return CBS_get_asn1(in, out, outer_tag); + } + + /* Otherwise, try to parse an implicitly-tagged constructed string. + * |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep + * of nesting. */ + CBB result; + CBS child; + if (!CBB_init(&result, CBS_len(in)) || + !CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) { + goto err; + } + + while (CBS_len(&child) > 0) { + CBS chunk; + if (!CBS_get_asn1(&child, &chunk, inner_tag) || + !CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) { + goto err; + } + } + + uint8_t *data; + size_t len; + if (!CBB_finish(&result, &data, &len)) { + goto err; + } + + CBS_init(out, data, len); + *out_storage = data; + return 1; + +err: + CBB_cleanup(&result); + return 0; +} diff --git a/external/boringssl/crypto/bytestring/bytestring_test.cc b/external/boringssl/crypto/bytestring/bytestring_test.cc new file mode 100644 index 0000000000..e1d16f49c4 --- /dev/null +++ b/external/boringssl/crypto/bytestring/bytestring_test.cc @@ -0,0 +1,825 @@ +/* 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(__STDC_CONSTANT_MACROS) +#define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include + +#include + +#include +#include + +#include "internal.h" +#include "../test/scoped_types.h" + + +static bool TestSkip() { + 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 bool TestGetUint() { + static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + 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_last_u8(&data, &u8) && + u8 == 0xb && + !CBS_get_u8(&data, &u8) && + !CBS_get_last_u8(&data, &u8); +} + +static bool TestGetPrefixed() { + 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 bool TestGetPrefixedBad() { + 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 false; + } + + CBS_init(&data, kData2, sizeof(kData2)); + if (CBS_get_u16_length_prefixed(&data, &prefixed)) { + return false; + } + + CBS_init(&data, kData3, sizeof(kData3)); + if (CBS_get_u24_length_prefixed(&data, &prefixed)) { + return false; + } + + return true; +} + +static bool TestGetASN1() { + static const uint8_t kData1[] = {0x30, 2, 1, 2}; + static const uint8_t kData2[] = {0x30, 3, 1, 2}; + static const uint8_t kData3[] = {0x30, 0x80}; + static const uint8_t kData4[] = {0x30, 0x81, 1, 1}; + static const uint8_t kData5[4 + 0x80] = {0x30, 0x82, 0, 0x80}; + static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1}; + static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1}; + static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1}; + static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff}; + + CBS data, contents; + int present; + uint64_t value; + + CBS_init(&data, kData1, sizeof(kData1)); + if (CBS_peek_asn1_tag(&data, 0x1) || + !CBS_peek_asn1_tag(&data, 0x30)) { + return false; + } + if (!CBS_get_asn1(&data, &contents, 0x30) || + CBS_len(&contents) != 2 || + memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) { + return false; + } + + CBS_init(&data, kData2, sizeof(kData2)); + // data is truncated + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData3, sizeof(kData3)); + // zero byte length of length + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData4, sizeof(kData4)); + // long form mistakenly used. + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData5, sizeof(kData5)); + // length takes too many bytes. + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData1, sizeof(kData1)); + // wrong tag. + if (CBS_get_asn1(&data, &contents, 0x31)) { + return false; + } + + CBS_init(&data, NULL, 0); + // peek at empty data. + if (CBS_peek_asn1_tag(&data, 0x30)) { + return false; + } + + 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 false; + } + + 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 false; + } + + 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 false; + } + + CBS_init(&data, kData7, sizeof(kData7)); + // invalid optional octet string. + if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) { + return false; + } + + 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 false; + } + + CBS_init(&data, kData9, sizeof(kData9)); + // invalid optional integer. + if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) { + return false; + } + + return true; +} + +static bool TestGetOptionalASN1Bool() { + 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 data; + CBS_init(&data, NULL, 0); + int val = 2; + if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) || + val != 0) { + return false; + } + + CBS_init(&data, kTrue, sizeof(kTrue)); + val = 2; + if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) || + val != 1) { + return false; + } + + CBS_init(&data, kFalse, sizeof(kFalse)); + val = 2; + if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) || + val != 0) { + return false; + } + + CBS_init(&data, kInvalid, sizeof(kInvalid)); + if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) { + return false; + } + + return true; +} + +static bool TestCBBBasic() { + static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8}; + uint8_t *buf; + size_t buf_len; + CBB cbb; + + if (!CBB_init(&cbb, 100)) { + return false; + } + CBB_cleanup(&cbb); + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!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)) { + CBB_cleanup(&cbb); + return false; + } + + ScopedOpenSSLBytes scoper(buf); + return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; +} + +static bool TestCBBFixed() { + 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 false; + } + + 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 false; + } + + return true; +} + +static bool TestCBBFinishChild() { + CBB cbb, child; + uint8_t *out_buf; + size_t out_size; + + if (!CBB_init(&cbb, 16)) { + return false; + } + if (!CBB_add_u8_length_prefixed(&cbb, &child) || + CBB_finish(&child, &out_buf, &out_size) || + !CBB_finish(&cbb, &out_buf, &out_size)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(out_buf); + return out_size == 1 && out_buf[0] == 0; +} + +static bool TestCBBPrefixed() { + 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; + + if (!CBB_init(&cbb, 0) || + CBB_len(&cbb) != 0 || + !CBB_add_u8_length_prefixed(&cbb, &contents) || + !CBB_add_u8_length_prefixed(&cbb, &contents) || + !CBB_add_u8(&contents, 1) || + CBB_len(&contents) != 1 || + !CBB_flush(&cbb) || + CBB_len(&cbb) != 3 || + !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)) { + CBB_cleanup(&cbb); + return false; + } + + ScopedOpenSSLBytes scoper(buf); + return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; +} + +static bool TestCBBDiscardChild() { + ScopedCBB cbb; + CBB contents, inner_contents, inner_inner_contents; + + if (!CBB_init(cbb.get(), 0) || + !CBB_add_u8(cbb.get(), 0xaa)) { + return false; + } + + // Discarding |cbb|'s children preserves the byte written. + CBB_discard_child(cbb.get()); + + if (!CBB_add_u8_length_prefixed(cbb.get(), &contents) || + !CBB_add_u8_length_prefixed(cbb.get(), &contents) || + !CBB_add_u8(&contents, 0xbb) || + !CBB_add_u16_length_prefixed(cbb.get(), &contents) || + !CBB_add_u16(&contents, 0xcccc) || + !CBB_add_u24_length_prefixed(cbb.get(), &contents) || + !CBB_add_u24(&contents, 0xdddddd) || + !CBB_add_u8_length_prefixed(cbb.get(), &contents) || + !CBB_add_u8(&contents, 0xff) || + !CBB_add_u8_length_prefixed(&contents, &inner_contents) || + !CBB_add_u8(&inner_contents, 0x42) || + !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) || + !CBB_add_u8(&inner_inner_contents, 0x99)) { + return false; + } + + // Discard everything from |inner_contents| down. + CBB_discard_child(&contents); + + uint8_t *buf; + size_t buf_len; + if (!CBB_finish(cbb.get(), &buf, &buf_len)) { + return false; + } + ScopedOpenSSLBytes scoper(buf); + + static const uint8_t kExpected[] = { + 0xaa, + 0, + 1, 0xbb, + 0, 2, 0xcc, 0xcc, + 0, 0, 3, 0xdd, 0xdd, 0xdd, + 1, 0xff, + }; + return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; +} + +static bool TestCBBMisuse() { + CBB cbb, child, contents; + uint8_t *buf; + size_t buf_len; + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_u8_length_prefixed(&cbb, &child) || + !CBB_add_u8(&child, 1) || + !CBB_add_u8(&cbb, 2)) { + CBB_cleanup(&cbb); + return false; + } + + // 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"); + CBB_cleanup(&cbb); + return false; + } + + if (!CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(buf); + + if (buf_len != 3 || + memcmp(buf, "\x01\x01\x02", 3) != 0) { + return false; + } + return true; +} + +static bool TestCBBASN1() { + static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3}; + uint8_t *buf; + size_t buf_len; + CBB cbb, contents, inner_contents; + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(buf); + + if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) { + return false; + } + + std::vector test_data(100000, 0x42); + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_bytes(&contents, test_data.data(), 130) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + scoper.reset(buf); + + if (buf_len != 3 + 130 || + memcmp(buf, "\x30\x81\x82", 3) != 0 || + memcmp(buf + 3, test_data.data(), 130) != 0) { + return false; + } + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_bytes(&contents, test_data.data(), 1000) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + scoper.reset(buf); + + if (buf_len != 4 + 1000 || + memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 || + memcmp(buf + 4, test_data.data(), 1000)) { + return false; + } + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_asn1(&contents, &inner_contents, 0x30) || + !CBB_add_bytes(&inner_contents, test_data.data(), 100000) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + scoper.reset(buf); + + 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.data(), 100000)) { + return false; + } + + return true; +} + +static bool DoBerConvert(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 false; + } + ScopedOpenSSLBytes scoper(out); + + if (out == NULL) { + if (ber_len != der_len || + memcmp(der_expected, ber, ber_len) != 0) { + fprintf(stderr, "%s: incorrect unconverted result.\n", name); + return false; + } + + return true; + } + + if (out_len != der_len || + memcmp(out, der_expected, der_len) != 0) { + fprintf(stderr, "%s: incorrect converted result.\n", name); + return false; + } + + return true; +} + +static bool TestBerConvert() { + 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 OCTET STRING 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, + }; + + // kConstructedStringBER contains a deeply-nested constructed OCTET STRING. + // The BER conversion collapses this to one level deep, but not completely. + static const uint8_t kConstructedStringBER[] = { + 0xa0, 0x10, 0x24, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, + 0x01, 0x24, 0x06, 0x04, 0x01, 0x02, 0x04, 0x01, 0x03, + }; + static const uint8_t kConstructedStringDER[] = { + 0xa0, 0x08, 0x04, 0x02, 0x00, 0x01, 0x04, 0x02, 0x02, 0x03, + }; + + return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER), + kSimpleBER, sizeof(kSimpleBER)) && + DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER, + sizeof(kIndefBER)) && + DoBerConvert("kOctetStringBER", kOctetStringDER, + sizeof(kOctetStringDER), kOctetStringBER, + sizeof(kOctetStringBER)) && + DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER, + sizeof(kNSSBER)) && + DoBerConvert("kConstructedStringBER", kConstructedStringDER, + sizeof(kConstructedStringDER), kConstructedStringBER, + sizeof(kConstructedStringBER)); +} + +struct ImplicitStringTest { + const char *in; + size_t in_len; + bool ok; + const char *out; + size_t out_len; +}; + +static const ImplicitStringTest kImplicitStringTests[] = { + // A properly-encoded string. + {"\x80\x03\x61\x61\x61", 5, true, "aaa", 3}, + // An implicit-tagged string. + {"\xa0\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, true, "aaa", 3}, + // |CBS_get_asn1_implicit_string| only accepts one level deep of nesting. + {"\xa0\x0b\x24\x06\x04\x01\x61\x04\x01\x61\x04\x01\x61", 13, false, nullptr, + 0}, + // The outer tag must match. + {"\x81\x03\x61\x61\x61", 5, false, nullptr, 0}, + {"\xa1\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, false, nullptr, 0}, + // The inner tag must match. + {"\xa1\x09\x0c\x01\x61\x0c\x01\x61\x0c\x01\x61", 11, false, nullptr, 0}, +}; + +static bool TestImplicitString() { + for (const auto &test : kImplicitStringTests) { + uint8_t *storage = nullptr; + CBS in, out; + CBS_init(&in, reinterpret_cast(test.in), test.in_len); + int ok = CBS_get_asn1_implicit_string(&in, &out, &storage, + CBS_ASN1_CONTEXT_SPECIFIC | 0, + CBS_ASN1_OCTETSTRING); + ScopedOpenSSLBytes scoper(storage); + + if (static_cast(ok) != test.ok) { + fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n", + ok ? "succeeded" : "failed"); + return false; + } + + if (ok && (CBS_len(&out) != test.out_len || + memcmp(CBS_data(&out), test.out, test.out_len) != 0)) { + fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n"); + return false; + } + } + + return true; +} + +struct ASN1Uint64Test { + uint64_t value; + const char *encoding; + size_t encoding_len; +}; + +static const ASN1Uint64Test 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}, + {UINT64_C(0x0102030405060708), + "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10}, + {UINT64_C(0xffffffffffffffff), + "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11}, +}; + +struct ASN1InvalidUint64Test { + const char *encoding; + size_t encoding_len; +}; + +static const ASN1InvalidUint64Test kASN1InvalidUint64Tests[] = { + // Bad tag. + {"\x03\x01\x00", 3}, + // Empty contents. + {"\x02\x00", 2}, + // Negative number. + {"\x02\x01\x80", 3}, + // Overflow. + {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11}, + // Leading zeros. + {"\x02\x02\x00\x01", 4}, +}; + +static bool TestASN1Uint64() { + for (size_t i = 0; i < sizeof(kASN1Uint64Tests) / sizeof(kASN1Uint64Tests[0]); + i++) { + const ASN1Uint64Test *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 false; + } + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1_uint64(&cbb, test->value) || + !CBB_finish(&cbb, &out, &len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(out); + if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) { + return false; + } + } + + for (size_t i = 0; + i < sizeof(kASN1InvalidUint64Tests) / sizeof(kASN1InvalidUint64Tests[0]); + i++) { + const ASN1InvalidUint64Test *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 false; + } + } + + return true; +} + +static bool TestZero() { + CBB cbb; + CBB_zero(&cbb); + // Calling |CBB_cleanup| on a zero-state |CBB| must not crash. + CBB_cleanup(&cbb); + return true; +} + +static bool TestCBBReserve() { + uint8_t buf[10]; + uint8_t *ptr; + size_t len; + ScopedCBB cbb; + if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) || + // Too large. + CBB_reserve(cbb.get(), &ptr, 11) || + // Successfully reserve the entire space. + !CBB_reserve(cbb.get(), &ptr, 10) || + ptr != buf || + // Advancing under the maximum bytes is legal. + !CBB_did_write(cbb.get(), 5) || + !CBB_finish(cbb.get(), NULL, &len) || + len != 5) { + return false; + } + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestSkip() || + !TestGetUint() || + !TestGetPrefixed() || + !TestGetPrefixedBad() || + !TestGetASN1() || + !TestCBBBasic() || + !TestCBBFixed() || + !TestCBBFinishChild() || + !TestCBBMisuse() || + !TestCBBPrefixed() || + !TestCBBDiscardChild() || + !TestCBBASN1() || + !TestBerConvert() || + !TestImplicitString() || + !TestASN1Uint64() || + !TestGetOptionalASN1Bool() || + !TestZero() || + !TestCBBReserve()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/bytestring/cbb.c b/external/boringssl/crypto/bytestring/cbb.c new file mode 100644 index 0000000000..8fc518794d --- /dev/null +++ b/external/boringssl/crypto/bytestring/cbb.c @@ -0,0 +1,445 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include + + +void CBB_zero(CBB *cbb) { + memset(cbb, 0, sizeof(CBB)); +} + +static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) { + /* This assumes that |cbb| has already been zeroed. */ + struct cbb_buffer_st *base; + + base = OPENSSL_malloc(sizeof(struct cbb_buffer_st)); + if (base == NULL) { + return 0; + } + + base->buf = buf; + base->len = 0; + base->cap = cap; + base->can_resize = 1; + + cbb->base = base; + cbb->is_top_level = 1; + return 1; +} + +int CBB_init(CBB *cbb, size_t initial_capacity) { + CBB_zero(cbb); + + uint8_t *buf = OPENSSL_malloc(initial_capacity); + if (initial_capacity > 0 && buf == NULL) { + return 0; + } + + if (!cbb_init(cbb, buf, initial_capacity)) { + OPENSSL_free(buf); + return 0; + } + + return 1; +} + +int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { + CBB_zero(cbb); + + if (!cbb_init(cbb, buf, len)) { + return 0; + } + + cbb->base->can_resize = 0; + return 1; +} + +void CBB_cleanup(CBB *cbb) { + if (cbb->base) { + /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They + * are implicitly discarded when the parent is flushed or cleaned up. */ + assert(cbb->is_top_level); + + if (cbb->base->can_resize) { + OPENSSL_free(cbb->base->buf); + } + OPENSSL_free(cbb->base); + } + cbb->base = NULL; +} + +static int cbb_buffer_reserve(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; + } + + return 1; +} + +static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, + size_t len) { + if (!cbb_buffer_reserve(base, out, len)) { + return 0; + } + /* This will not overflow or |cbb_buffer_reserve| would have failed. */ + base->len += len; + 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->child->pending_len_len == 0) { + return 1; + } + + child_start = cbb->child->offset + cbb->child->pending_len_len; + + if (!CBB_flush(cbb->child) || + child_start < cbb->child->offset || + cbb->base->len < child_start) { + return 0; + } + + len = cbb->base->len - child_start; + + if (cbb->child->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->child->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->child->offset++] = initial_length_byte; + cbb->child->pending_len_len = len_len - 1; + } + + for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len; + i--) { + cbb->base->buf[cbb->child->offset + i] = len; + len >>= 8; + } + if (len != 0) { + return 0; + } + + cbb->child->base = NULL; + cbb->child = NULL; + + return 1; +} + +const uint8_t *CBB_data(const CBB *cbb) { + assert(cbb->child == NULL); + return cbb->base->buf + cbb->offset + cbb->pending_len_len; +} + +size_t CBB_len(const CBB *cbb) { + assert(cbb->child == NULL); + assert(cbb->offset + cbb->pending_len_len <= cbb->base->len); + + return cbb->base->len - cbb->offset - cbb->pending_len_len; +} + +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; + } + + size_t 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->child->offset = offset; + cbb->child->pending_len_len = len_len; + cbb->child->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 ((tag & 0x1f) == 0x1f) { + /* Long form identifier octets are not supported. */ + return 0; + } + + if (!CBB_flush(cbb) || + !CBB_add_u8(cbb, tag)) { + return 0; + } + + size_t 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->child->offset = offset; + cbb->child->pending_len_len = 1; + cbb->child->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_reserve(CBB *cbb, uint8_t **out_data, size_t len) { + if (!CBB_flush(cbb) || + !cbb_buffer_reserve(cbb->base, out_data, len)) { + return 0; + } + return 1; +} + +int CBB_did_write(CBB *cbb, size_t len) { + size_t newlen = cbb->base->len + len; + if (cbb->child != NULL || + newlen < cbb->base->len || + newlen > cbb->base->cap) { + return 0; + } + cbb->base->len = newlen; + 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); +} + +void CBB_discard_child(CBB *cbb) { + if (cbb->child == NULL) { + return; + } + + cbb->base->len = cbb->child->offset; + + cbb->child->base = NULL; + cbb->child = NULL; +} + +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/external/boringssl/crypto/bytestring/cbs.c b/external/boringssl/crypto/bytestring/cbs.c new file mode 100644 index 0000000000..c86afbda91 --- /dev/null +++ b/external/boringssl/crypto/bytestring/cbs.c @@ -0,0 +1,440 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include + +#include "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) { + 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_last_u8(CBS *cbs, uint8_t *out) { + if (cbs->len == 0) { + return 0; + } + *out = cbs->data[cbs->len - 1]; + cbs->len--; + return 1; +} + +int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) { + const uint8_t *v; + if (!cbs_get(cbs, &v, len)) { + return 0; + } + CBS_init(out, v, len); + return 1; +} + +int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) { + const uint8_t *v; + if (!cbs_get(cbs, &v, len)) { + return 0; + } + memcpy(out, v, len); + return 1; +} + +static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) { + uint32_t len; + if (!cbs_get_u(cbs, &len, len_len)) { + return 0; + } + return CBS_get_bytes(cbs, out, len); +} + +int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) { + return cbs_get_length_prefixed(cbs, out, 1); +} + +int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) { + return cbs_get_length_prefixed(cbs, out, 2); +} + +int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) { + return cbs_get_length_prefixed(cbs, out, 3); +} + +static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, + size_t *out_header_len, int ber_ok) { + 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; + } + + /* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag + * number no greater than 30. + * + * If the number portion is 31 (0x1f, the largest value that fits in the + * allotted bits), then the tag is more than one byte long and the + * continuation bytes contain the tag number. This parser only supports tag + * numbers less than 31 (and thus single-byte tags). */ + if ((tag & 0x1f) == 0x1f) { + return 0; + } + + if (out_tag != NULL) { + *out_tag = tag; + } + + size_t len; + /* The format for the length encoding is specified in ITU-T X.690 section + * 8.1.3. */ + if ((length_byte & 0x80) == 0) { + /* Short form length. */ + len = ((size_t) length_byte) + 2; + if (out_header_len != NULL) { + *out_header_len = 2; + } + } else { + /* The high bit indicate that this is the long form, while the next 7 bits + * encode the number of subsequent octets used to encode the length (ITU-T + * X.690 clause 8.1.3.5.b). */ + const size_t num_bytes = length_byte & 0x7f; + uint32_t len32; + + if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) { + /* indefinite length */ + if (out_header_len != NULL) { + *out_header_len = 2; + } + return CBS_get_bytes(cbs, out, 2); + } + + /* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be + * used as the first byte of the length. If this parser encounters that + * value, num_bytes will be parsed as 127, which will fail the check below. + */ + if (num_bytes == 0 || num_bytes > 4) { + return 0; + } + if (!cbs_get_u(&header, &len32, num_bytes)) { + return 0; + } + /* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length + * with the minimum number of octets. */ + 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); +} + +int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, + size_t *out_header_len) { + return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, + 0 /* DER only */); +} + +int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, + size_t *out_header_len) { + return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, + 1 /* BER allowed */); +} + +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) { + 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; + } + + if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) { + /* Extra leading zeros. */ + return 0; + } + + for (i = 0; i < len; i++) { + if ((*out >> 56) != 0) { + /* Too large to represent as a uint64_t. */ + return 0; + } + *out <<= 8; + *out |= data[i]; + } + + return 1; +} + +int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) { + int present = 0; + + if (CBS_peek_asn1_tag(cbs, tag)) { + if (!CBS_get_asn1(cbs, out, tag)) { + return 0; + } + present = 1; + } + + if (out_present != NULL) { + *out_present = present; + } + + 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/external/boringssl/crypto/bytestring/internal.h b/external/boringssl/crypto/bytestring/internal.h new file mode 100644 index 0000000000..2fed413902 --- /dev/null +++ b/external/boringssl/crypto/bytestring/internal.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 OPENSSL_HEADER_BYTESTRING_INTERNAL_H +#define OPENSSL_HEADER_BYTESTRING_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds + * indefinite-length elements or constructed strings then it converts 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 BER + * element. + * + * If it doesn't find any indefinite-length elements or constructed strings then + * it sets |*out| to NULL and |*in| is unmodified. + * + * This function should successfully process any valid BER input, however it + * will not convert all of BER's deviations from DER. BER is ambiguous between + * implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed + * strings. Implicitly-tagged strings must be parsed with + * |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller + * must also account for BER variations in the contents of a primitive. + * + * 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); + +/* CBS_get_asn1_implicit_string parses a BER string of primitive type + * |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the + * contents. If concatenation was needed, it sets |*out_storage| to a buffer + * which the caller must release with |OPENSSL_free|. Otherwise, it sets + * |*out_storage| to NULL. + * + * This function does not parse all of BER. It requires the string be + * definite-length. Constructed strings are allowed, but all children of the + * outermost element must be primitive. The caller should use + * |CBS_asn1_ber_to_der| before running this function. + * + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out, + uint8_t **out_storage, + unsigned outer_tag, + unsigned inner_tag); + +/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized + * with |CBB_init|. 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. On + * error, it calls |CBB_cleanup| on |cbb|. + * + * This function may be used to help implement legacy i2d ASN.1 functions. */ +int CBB_finish_i2d(CBB *cbb, uint8_t **outp); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BYTESTRING_INTERNAL_H */ diff --git a/external/boringssl/crypto/chacha/CMakeLists.txt b/external/boringssl/crypto/chacha/CMakeLists.txt new file mode 100644 index 0000000000..73cfc31edd --- /dev/null +++ b/external/boringssl/crypto/chacha/CMakeLists.txt @@ -0,0 +1,60 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "arm") + set( + CHACHA_ARCH_SOURCES + + chacha-armv4.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "aarch64") + set( + CHACHA_ARCH_SOURCES + + chacha-armv8.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + CHACHA_ARCH_SOURCES + + chacha-x86.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86_64") + set( + CHACHA_ARCH_SOURCES + + chacha-x86_64.${ASM_EXT} + ) +endif() + +add_library( + chacha + + OBJECT + + chacha.c + + ${CHACHA_ARCH_SOURCES} +) + +if(ENABLE_TESTS) +add_executable( + chacha_test + + chacha_test.cc + $ +) + +target_link_libraries(chacha_test crypto) +add_dependencies(all_tests chacha_test) +endif() + +perlasm(chacha-armv4.${ASM_EXT} asm/chacha-armv4.pl) +perlasm(chacha-armv8.${ASM_EXT} asm/chacha-armv8.pl) +perlasm(chacha-x86.${ASM_EXT} asm/chacha-x86.pl) +perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl) diff --git a/external/boringssl/crypto/chacha/asm/chacha-armv4.pl b/external/boringssl/crypto/chacha/asm/chacha-armv4.pl new file mode 100755 index 0000000000..b190445da5 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-armv4.pl @@ -0,0 +1,1151 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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/. +# ==================================================================== +# +# December 2014 +# +# ChaCha20 for ARMv4. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc-4.4 1xNEON 3xNEON+1xIALU +# +# Cortex-A5 19.3(*)/+95% 21.8 14.1 +# Cortex-A8 10.5(*)/+160% 13.9 6.35 +# Cortex-A9 12.9(**)/+110% 14.3 6.50 +# Cortex-A15 11.0/+40% 16.0 5.00 +# Snapdragon S4 11.5/+125% 13.6 4.90 +# +# (*) most "favourable" result for aligned data on little-endian +# processor, result for misaligned data is 10-15% lower; +# (**) this result is a trade-off: it can be improved by 20%, +# but then Snapdragon S4 and Cortex-A8 results get +# 20-25% worse; + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +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"; +} + +my @x=map("r$_",(0..7,"x","x","x","x",12,"x",14,"x")); +my @t=map("r$_",(8..11)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my $odd = $d0&1; +my ($xc,$xc_) = (@t[0..1]); +my ($xd,$xd_) = $odd ? (@t[2],@x[$d1]) : (@x[$d0],@t[2]); +my @ret; + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' are permanently allocated in registers, @x[0..7], + # while 'c's and pair of 'd's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. If you observe 'd' column, you'll + # notice that 15 and 13 are reused in next pair of rounds. + # This is why these two are chosen for offloading to memory, + # to make loads count more. + push @ret,( + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&mov ($xd,$xd,'ror#16')", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&mov ($xd_,$xd_,'ror#16')", + "&eor ($xd,$xd,@x[$a0],'ror#16')", + "&eor ($xd_,$xd_,@x[$a1],'ror#16')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b0],@x[$b0],'ror#20')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b1],@x[$b1],'ror#20')", + "&eor (@x[$b0],@x[$b0],$xc,'ror#20')", + "&eor (@x[$b1],@x[$b1],$xc_,'ror#20')", + + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&mov ($xd,$xd,'ror#24')", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&mov ($xd_,$xd_,'ror#24')", + "&eor ($xd,$xd,@x[$a0],'ror#24')", + "&eor ($xd_,$xd_,@x[$a1],'ror#24')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b0],@x[$b0],'ror#25')" ); + push @ret,( + "&str ($xd,'[sp,#4*(16+$d0)]')", + "&ldr ($xd,'[sp,#4*(16+$d2)]')" ) if ($odd); + push @ret,( + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b1],@x[$b1],'ror#25')" ); + push @ret,( + "&str ($xd_,'[sp,#4*(16+$d1)]')", + "&ldr ($xd_,'[sp,#4*(16+$d3)]')" ) if (!$odd); + push @ret,( + "&eor (@x[$b0],@x[$b0],$xc,'ror#25')", + "&eor (@x[$b1],@x[$b1],$xc_,'ror#25')" ); + + $xd=@x[$d2] if (!$odd); + $xd_=@x[$d3] if ($odd); + push @ret,( + "&str ($xc,'[sp,#4*(16+$c0)]')", + "&ldr ($xc,'[sp,#4*(16+$c2)]')", + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&mov ($xd,$xd,'ror#16')", + "&str ($xc_,'[sp,#4*(16+$c1)]')", + "&ldr ($xc_,'[sp,#4*(16+$c3)]')", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&mov ($xd_,$xd_,'ror#16')", + "&eor ($xd,$xd,@x[$a2],'ror#16')", + "&eor ($xd_,$xd_,@x[$a3],'ror#16')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b2],@x[$b2],'ror#20')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b3],@x[$b3],'ror#20')", + "&eor (@x[$b2],@x[$b2],$xc,'ror#20')", + "&eor (@x[$b3],@x[$b3],$xc_,'ror#20')", + + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&mov ($xd,$xd,'ror#24')", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&mov ($xd_,$xd_,'ror#24')", + "&eor ($xd,$xd,@x[$a2],'ror#24')", + "&eor ($xd_,$xd_,@x[$a3],'ror#24')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b2],@x[$b2],'ror#25')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b3],@x[$b3],'ror#25')", + "&eor (@x[$b2],@x[$b2],$xc,'ror#25')", + "&eor (@x[$b3],@x[$b3],$xc_,'ror#25')" ); + + @ret; +} + +$code.=<<___; +#include + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +#if defined(__thumb2__) || defined(__clang__) +#define ldrhsb ldrbhs +#endif + +.align 5 +.Lsigma: +.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 @ endian-neutral +.Lone: +.long 1,0,0,0 +#if __ARM_MAX_ARCH__>=7 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.LChaCha20_ctr32 +#else +.word -1 +#endif + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,%function +.align 5 +ChaCha20_ctr32: +.LChaCha20_ctr32: + ldr r12,[sp,#0] @ pull pointer to counter and nonce + stmdb sp!,{r0-r2,r4-r11,lr} +#if __ARM_ARCH__<7 && !defined(__thumb2__) + sub r14,pc,#16 @ ChaCha20_ctr32 +#else + adr r14,.LChaCha20_ctr32 +#endif + cmp r2,#0 @ len==0? +#ifdef __thumb2__ + itt eq +#endif + addeq sp,sp,#4*3 + beq .Lno_data +#if __ARM_MAX_ARCH__>=7 + cmp r2,#192 @ test len + bls .Lshort + ldr r4,[r14,#-32] + ldr r4,[r14,r4] +# ifdef __APPLE__ + ldr r4,[r4] +# endif + tst r4,#ARMV7_NEON + bne .LChaCha20_neon +.Lshort: +#endif + ldmia r12,{r4-r7} @ load counter and nonce + sub sp,sp,#4*(16) @ off-load area + sub r14,r14,#64 @ .Lsigma + stmdb sp!,{r4-r7} @ copy counter and nonce + ldmia r3,{r4-r11} @ load key + ldmia r14,{r0-r3} @ load sigma + stmdb sp!,{r4-r11} @ copy key + stmdb sp!,{r0-r3} @ copy sigma + str r10,[sp,#4*(16+10)] @ off-load "@x[10]" + str r11,[sp,#4*(16+11)] @ off-load "@x[11]" + b .Loop_outer_enter + +.align 4 +.Loop_outer: + ldmia sp,{r0-r9} @ load key material + str @t[3],[sp,#4*(32+2)] @ save len + str r12, [sp,#4*(32+1)] @ save inp + str r14, [sp,#4*(32+0)] @ save out +.Loop_outer_enter: + ldr @t[3], [sp,#4*(15)] + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + ldr @t[2], [sp,#4*(13)] + ldr @x[14],[sp,#4*(14)] + str @t[3], [sp,#4*(16+15)] + mov @t[3],#10 + b .Loop + +.align 4 +.Loop: + subs @t[3],@t[3],#1 +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + bne .Loop + + ldr @t[3],[sp,#4*(32+2)] @ load len + + str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store + str @t[1], [sp,#4*(16+9)] + str @x[12],[sp,#4*(16+12)] + str @t[2], [sp,#4*(16+13)] + str @x[14],[sp,#4*(16+14)] + + @ at this point we have first half of 512-bit result in + @ @x[0-7] and second half at sp+4*(16+8) + + cmp @t[3],#64 @ done yet? +#ifdef __thumb2__ + itete lo +#endif + addlo r12,sp,#4*(0) @ shortcut or ... + ldrhs r12,[sp,#4*(32+1)] @ ... load inp + addlo r14,sp,#4*(0) @ shortcut or ... + ldrhs r14,[sp,#4*(32+0)] @ ... load out + + ldr @t[0],[sp,#4*(0)] @ load key material + ldr @t[1],[sp,#4*(1)] + +#if __ARM_ARCH__>=6 || !defined(__ARMEB__) +# if __ARM_ARCH__<7 + orr @t[2],r12,r14 + tst @t[2],#3 @ are input and output aligned? + ldr @t[2],[sp,#4*(2)] + bne .Lunaligned + cmp @t[3],#64 @ restore flags +# else + ldr @t[2],[sp,#4*(2)] +# endif + ldr @t[3],[sp,#4*(3)] + + add @x[0],@x[0],@t[0] @ accumulate key material + add @x[1],@x[1],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[0],@x[0],@t[0] @ xor with input + eorhs @x[1],@x[1],@t[1] + add @t[0],sp,#4*(4) + str @x[0],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[2],@x[2],@t[2] + eorhs @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[1],[r14,#-12] + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @x[5],@x[5],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[4],@x[4],@t[0] + eorhs @x[5],@x[5],@t[1] + add @t[0],sp,#4*(8) + str @x[4],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[6],@x[6],@t[2] + eorhs @x[7],@x[7],@t[3] + str @x[5],[r14,#-12] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[6],[r14,#-8] + add @x[0],sp,#4*(16+8) + str @x[7],[r14,#-4] + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + add @x[1],@x[1],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] +# ifdef __thumb2__ + itt hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[0],@x[0],@t[0] + eorhs @x[1],@x[1],@t[1] + add @t[0],sp,#4*(12) + str @x[0],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[2],@x[2],@t[2] + eorhs @x[3],@x[3],@t[3] + str @x[1],[r14,#-12] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @x[5],@x[5],@t[1] +# ifdef __thumb2__ + itt hi +# endif + addhi @t[0],@t[0],#1 @ next counter value + strhi @t[0],[sp,#4*(12)] @ save next counter value +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[4],@x[4],@t[0] + eorhs @x[5],@x[5],@t[1] +# ifdef __thumb2__ + it ne +# endif + ldrne @t[0],[sp,#4*(32+2)] @ re-load len +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[6],@x[6],@t[2] + eorhs @x[7],@x[7],@t[3] + str @x[4],[r14],#16 @ store output + str @x[5],[r14,#-12] +# ifdef __thumb2__ + it hs +# endif + subhs @t[3],@t[0],#64 @ len-=64 + str @x[6],[r14,#-8] + str @x[7],[r14,#-4] + bhi .Loop_outer + + beq .Ldone +# if __ARM_ARCH__<7 + b .Ltail + +.align 4 +.Lunaligned: @ unaligned endian-neutral path + cmp @t[3],#64 @ restore flags +# endif +#endif +#if __ARM_ARCH__<7 + ldr @t[3],[sp,#4*(3)] +___ +for ($i=0;$i<16;$i+=4) { +my $j=$i&0x7; + +$code.=<<___ if ($i==4); + add @x[0],sp,#4*(16+8) +___ +$code.=<<___ if ($i==8); + ldmia @x[0],{@x[0]-@x[7]} @ load second half +# ifdef __thumb2__ + itt hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" +___ +$code.=<<___; + add @x[$j+0],@x[$j+0],@t[0] @ accumulate key material +___ +$code.=<<___ if ($i==12); +# ifdef __thumb2__ + itt hi +# endif + addhi @t[0],@t[0],#1 @ next counter value + strhi @t[0],[sp,#4*(12)] @ save next counter value +___ +$code.=<<___; + add @x[$j+1],@x[$j+1],@t[1] + add @x[$j+2],@x[$j+2],@t[2] +# ifdef __thumb2__ + itete lo +# endif + eorlo @t[0],@t[0],@t[0] @ zero or ... + ldrhsb @t[0],[r12],#16 @ ... load input + eorlo @t[1],@t[1],@t[1] + ldrhsb @t[1],[r12,#-12] + + add @x[$j+3],@x[$j+3],@t[3] +# ifdef __thumb2__ + itete lo +# endif + eorlo @t[2],@t[2],@t[2] + ldrhsb @t[2],[r12,#-8] + eorlo @t[3],@t[3],@t[3] + ldrhsb @t[3],[r12,#-4] + + eor @x[$j+0],@t[0],@x[$j+0] @ xor with input (or zero) + eor @x[$j+1],@t[1],@x[$j+1] +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-15] @ load more input + ldrhsb @t[1],[r12,#-11] + eor @x[$j+2],@t[2],@x[$j+2] + strb @x[$j+0],[r14],#16 @ store output + eor @x[$j+3],@t[3],@x[$j+3] +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-7] + ldrhsb @t[3],[r12,#-3] + strb @x[$j+1],[r14,#-12] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+2],[r14,#-8] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-14] @ load more input + ldrhsb @t[1],[r12,#-10] + strb @x[$j+3],[r14,#-4] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+0],[r14,#-15] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-6] + ldrhsb @t[3],[r12,#-2] + strb @x[$j+1],[r14,#-11] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+2],[r14,#-7] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-13] @ load more input + ldrhsb @t[1],[r12,#-9] + strb @x[$j+3],[r14,#-3] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+0],[r14,#-14] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-5] + ldrhsb @t[3],[r12,#-1] + strb @x[$j+1],[r14,#-10] + strb @x[$j+2],[r14,#-6] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+3],[r14,#-2] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 + strb @x[$j+0],[r14,#-13] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+1],[r14,#-9] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 + strb @x[$j+2],[r14,#-5] + strb @x[$j+3],[r14,#-1] +___ +$code.=<<___ if ($i<12); + add @t[0],sp,#4*(4+$i) + ldmia @t[0],{@t[0]-@t[3]} @ load key material +___ +} +$code.=<<___; +# ifdef __thumb2__ + it ne +# endif + ldrne @t[0],[sp,#4*(32+2)] @ re-load len +# ifdef __thumb2__ + it hs +# endif + subhs @t[3],@t[0],#64 @ len-=64 + bhi .Loop_outer + + beq .Ldone +#endif + +.Ltail: + ldr r12,[sp,#4*(32+1)] @ load inp + add @t[1],sp,#4*(0) + ldr r14,[sp,#4*(32+0)] @ load out + +.Loop_tail: + ldrb @t[2],[@t[1]],#1 @ read buffer on stack + ldrb @t[3],[r12],#1 @ read input + subs @t[0],@t[0],#1 + eor @t[3],@t[3],@t[2] + strb @t[3],[r14],#1 @ store output + bne .Loop_tail + +.Ldone: + add sp,sp,#4*(32+3) +.Lno_data: + ldmia sp!,{r4-r11,pc} +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +{{{ +my ($a0,$b0,$c0,$d0,$a1,$b1,$c1,$d1,$a2,$b2,$c2,$d2,$t0,$t1,$t2,$t3) = + map("q$_",(0..15)); + +sub NEONROUND { +my $odd = pop; +my ($a,$b,$c,$d,$t)=@_; + + ( + "&vadd_i32 ($a,$a,$b)", + "&veor ($d,$d,$a)", + "&vrev32_16 ($d,$d)", # vrot ($d,16) + + "&vadd_i32 ($c,$c,$d)", + "&veor ($t,$b,$c)", + "&vshr_u32 ($b,$t,20)", + "&vsli_32 ($b,$t,12)", + + "&vadd_i32 ($a,$a,$b)", + "&veor ($t,$d,$a)", + "&vshr_u32 ($d,$t,24)", + "&vsli_32 ($d,$t,8)", + + "&vadd_i32 ($c,$c,$d)", + "&veor ($t,$b,$c)", + "&vshr_u32 ($b,$t,25)", + "&vsli_32 ($b,$t,7)", + + "&vext_8 ($c,$c,$c,8)", + "&vext_8 ($b,$b,$b,$odd?12:4)", + "&vext_8 ($d,$d,$d,$odd?4:12)" + ); +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.type ChaCha20_neon,%function +.align 5 +ChaCha20_neon: + ldr r12,[sp,#0] @ pull pointer to counter and nonce + stmdb sp!,{r0-r2,r4-r11,lr} +.LChaCha20_neon: + adr r14,.Lsigma + vstmdb sp!,{d8-d15} @ ABI spec says so + stmdb sp!,{r0-r3} + + vld1.32 {$b0-$c0},[r3] @ load key + ldmia r3,{r4-r11} @ load key + + sub sp,sp,#4*(16+16) + vld1.32 {$d0},[r12] @ load counter and nonce + add r12,sp,#4*8 + ldmia r14,{r0-r3} @ load sigma + vld1.32 {$a0},[r14]! @ load sigma + vld1.32 {$t0},[r14] @ one + vst1.32 {$c0-$d0},[r12] @ copy 1/2key|counter|nonce + vst1.32 {$a0-$b0},[sp] @ copy sigma|1/2key + + str r10,[sp,#4*(16+10)] @ off-load "@x[10]" + str r11,[sp,#4*(16+11)] @ off-load "@x[11]" + vshl.i32 $t1#lo,$t0#lo,#1 @ two + vstr $t0#lo,[sp,#4*(16+0)] + vshl.i32 $t2#lo,$t0#lo,#2 @ four + vstr $t1#lo,[sp,#4*(16+2)] + vmov $a1,$a0 + vstr $t2#lo,[sp,#4*(16+4)] + vmov $a2,$a0 + vmov $b1,$b0 + vmov $b2,$b0 + b .Loop_neon_enter + +.align 4 +.Loop_neon_outer: + ldmia sp,{r0-r9} @ load key material + cmp @t[3],#64*2 @ if len<=64*2 + bls .Lbreak_neon @ switch to integer-only + vmov $a1,$a0 + str @t[3],[sp,#4*(32+2)] @ save len + vmov $a2,$a0 + str r12, [sp,#4*(32+1)] @ save inp + vmov $b1,$b0 + str r14, [sp,#4*(32+0)] @ save out + vmov $b2,$b0 +.Loop_neon_enter: + ldr @t[3], [sp,#4*(15)] + vadd.i32 $d1,$d0,$t0 @ counter+1 + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + vmov $c1,$c0 + ldr @t[2], [sp,#4*(13)] + vmov $c2,$c0 + ldr @x[14],[sp,#4*(14)] + vadd.i32 $d2,$d1,$t0 @ counter+2 + str @t[3], [sp,#4*(16+15)] + mov @t[3],#10 + add @x[12],@x[12],#3 @ counter+3 + b .Loop_neon + +.align 4 +.Loop_neon: + subs @t[3],@t[3],#1 +___ + my @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,0); + my @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,0); + my @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,0); + my @thread3=&ROUND(0,4,8,12); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } + + @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,1); + @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,1); + @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,1); + @thread3=&ROUND(0,5,10,15); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } +$code.=<<___; + bne .Loop_neon + + add @t[3],sp,#32 + vld1.32 {$t0-$t1},[sp] @ load key material + vld1.32 {$t2-$t3},[@t[3]] + + ldr @t[3],[sp,#4*(32+2)] @ load len + + str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store + str @t[1], [sp,#4*(16+9)] + str @x[12],[sp,#4*(16+12)] + str @t[2], [sp,#4*(16+13)] + str @x[14],[sp,#4*(16+14)] + + @ at this point we have first half of 512-bit result in + @ @x[0-7] and second half at sp+4*(16+8) + + ldr r12,[sp,#4*(32+1)] @ load inp + ldr r14,[sp,#4*(32+0)] @ load out + + vadd.i32 $a0,$a0,$t0 @ accumulate key material + vadd.i32 $a1,$a1,$t0 + vadd.i32 $a2,$a2,$t0 + vldr $t0#lo,[sp,#4*(16+0)] @ one + + vadd.i32 $b0,$b0,$t1 + vadd.i32 $b1,$b1,$t1 + vadd.i32 $b2,$b2,$t1 + vldr $t1#lo,[sp,#4*(16+2)] @ two + + vadd.i32 $c0,$c0,$t2 + vadd.i32 $c1,$c1,$t2 + vadd.i32 $c2,$c2,$t2 + vadd.i32 $d1#lo,$d1#lo,$t0#lo @ counter+1 + vadd.i32 $d2#lo,$d2#lo,$t1#lo @ counter+2 + + vadd.i32 $d0,$d0,$t3 + vadd.i32 $d1,$d1,$t3 + vadd.i32 $d2,$d2,$t3 + + cmp @t[3],#64*4 + blo .Ltail_neon + + vld1.8 {$t0-$t1},[r12]! @ load input + mov @t[3],sp + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 @ xor with input + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + vst1.8 {$a0-$b0},[r14]! @ store output + veor $b1,$b1,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c1,$c1,$t2 + vst1.8 {$c0-$d0},[r14]! + veor $d1,$d1,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a2,$a2,$t0 + vld1.32 {$a0-$b0},[@t[3]]! @ load for next iteration + veor $t0#hi,$t0#hi,$t0#hi + vldr $t0#lo,[sp,#4*(16+4)] @ four + veor $b2,$b2,$t1 + vld1.32 {$c0-$d0},[@t[3]] + veor $c2,$c2,$t2 + vst1.8 {$a1-$b1},[r14]! + veor $d2,$d2,$t3 + vst1.8 {$c1-$d1},[r14]! + + vadd.i32 $d0#lo,$d0#lo,$t0#lo @ next counter value + vldr $t0#lo,[sp,#4*(16+0)] @ one + + ldmia sp,{@t[0]-@t[3]} @ load key material + add @x[0],@x[0],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + vst1.8 {$a2-$b2},[r14]! + add @x[1],@x[1],@t[1] + ldr @t[1],[r12,#-12] + vst1.8 {$c2-$d2},[r14]! + add @x[2],@x[2],@t[2] + ldr @t[2],[r12,#-8] + add @x[3],@x[3],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif + eor @x[0],@x[0],@t[0] @ xor with input + add @t[0],sp,#4*(4) + eor @x[1],@x[1],@t[1] + str @x[0],[r14],#16 @ store output + eor @x[2],@x[2],@t[2] + str @x[1],[r14,#-12] + eor @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + add @x[5],@x[5],@t[1] + ldr @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + ldr @t[2],[r12,#-8] + add @x[7],@x[7],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + eor @x[4],@x[4],@t[0] + add @t[0],sp,#4*(8) + eor @x[5],@x[5],@t[1] + str @x[4],[r14],#16 @ store output + eor @x[6],@x[6],@t[2] + str @x[5],[r14,#-12] + eor @x[7],@x[7],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[6],[r14,#-8] + add @x[0],sp,#4*(16+8) + str @x[7],[r14,#-4] + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + add @x[1],@x[1],@t[1] + ldr @t[1],[r12,#-12] +# ifdef __thumb2__ + it hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it + add @x[2],@x[2],@t[2] + ldr @t[2],[r12,#-8] +# ifdef __thumb2__ + it hi +# endif + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it + add @x[3],@x[3],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif + eor @x[0],@x[0],@t[0] + add @t[0],sp,#4*(12) + eor @x[1],@x[1],@t[1] + str @x[0],[r14],#16 @ store output + eor @x[2],@x[2],@t[2] + str @x[1],[r14,#-12] + eor @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],@t[0],#4 @ next counter value + add @x[5],@x[5],@t[1] + str @t[0],[sp,#4*(12)] @ save next counter value + ldr @t[0],[r12],#16 @ load input + add @x[6],@x[6],@t[2] + add @x[4],@x[4],#3 @ counter+3 + ldr @t[1],[r12,#-12] + add @x[7],@x[7],@t[3] + ldr @t[2],[r12,#-8] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + eor @x[4],@x[4],@t[0] +# ifdef __thumb2__ + it hi +# endif + ldrhi @t[0],[sp,#4*(32+2)] @ re-load len + eor @x[5],@x[5],@t[1] + eor @x[6],@x[6],@t[2] + str @x[4],[r14],#16 @ store output + eor @x[7],@x[7],@t[3] + str @x[5],[r14,#-12] + sub @t[3],@t[0],#64*4 @ len-=64*4 + str @x[6],[r14,#-8] + str @x[7],[r14,#-4] + bhi .Loop_neon_outer + + b .Ldone_neon + +.align 4 +.Lbreak_neon: + @ harmonize NEON and integer-only stack frames: load data + @ from NEON frame, but save to integer-only one; distance + @ between the two is 4*(32+4+16-32)=4*(20). + + str @t[3], [sp,#4*(20+32+2)] @ save len + add @t[3],sp,#4*(32+4) + str r12, [sp,#4*(20+32+1)] @ save inp + str r14, [sp,#4*(20+32+0)] @ save out + + ldr @x[12],[sp,#4*(16+10)] + ldr @x[14],[sp,#4*(16+11)] + vldmia @t[3],{d8-d15} @ fulfill ABI requirement + str @x[12],[sp,#4*(20+16+10)] @ copy "@x[10]" + str @x[14],[sp,#4*(20+16+11)] @ copy "@x[11]" + + ldr @t[3], [sp,#4*(15)] + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + ldr @t[2], [sp,#4*(13)] + ldr @x[14],[sp,#4*(14)] + str @t[3], [sp,#4*(20+16+15)] + add @t[3],sp,#4*(20) + vst1.32 {$a0-$b0},[@t[3]]! @ copy key + add sp,sp,#4*(20) @ switch frame + vst1.32 {$c0-$d0},[@t[3]] + mov @t[3],#10 + b .Loop @ go integer-only + +.align 4 +.Ltail_neon: + cmp @t[3],#64*3 + bhs .L192_or_more_neon + cmp @t[3],#64*2 + bhs .L128_or_more_neon + cmp @t[3],#64*1 + bhs .L64_or_more_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a0-$b0},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c0-$d0},[@t[0]] + b .Loop_tail_neon + +.align 4 +.L64_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vst1.8 {$a0-$b0},[r14]! + vst1.8 {$c0-$d0},[r14]! + + beq .Ldone_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a1-$b1},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c1-$d1},[@t[0]] + sub @t[3],@t[3],#64*1 @ len-=64*1 + b .Loop_tail_neon + +.align 4 +.L128_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + veor $b1,$b1,$t1 + vst1.8 {$a0-$b0},[r14]! + veor $c1,$c1,$t2 + vst1.8 {$c0-$d0},[r14]! + veor $d1,$d1,$t3 + vst1.8 {$a1-$b1},[r14]! + vst1.8 {$c1-$d1},[r14]! + + beq .Ldone_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a2-$b2},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c2-$d2},[@t[0]] + sub @t[3],@t[3],#64*2 @ len-=64*2 + b .Loop_tail_neon + +.align 4 +.L192_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + veor $b1,$b1,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c1,$c1,$t2 + vst1.8 {$a0-$b0},[r14]! + veor $d1,$d1,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a2,$a2,$t0 + vst1.8 {$c0-$d0},[r14]! + veor $b2,$b2,$t1 + vst1.8 {$a1-$b1},[r14]! + veor $c2,$c2,$t2 + vst1.8 {$c1-$d1},[r14]! + veor $d2,$d2,$t3 + vst1.8 {$a2-$b2},[r14]! + vst1.8 {$c2-$d2},[r14]! + + beq .Ldone_neon + + ldmia sp,{@t[0]-@t[3]} @ load key material + add @x[0],@x[0],@t[0] @ accumulate key material + add @t[0],sp,#4*(4) + add @x[1],@x[1],@t[1] + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],sp,#4*(8) + add @x[5],@x[5],@t[1] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + stmia sp,{@x[0]-@x[7]} + add @x[0],sp,#4*(16+8) + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + add @t[0],sp,#4*(12) + add @x[1],@x[1],@t[1] + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],sp,#4*(8) + add @x[5],@x[5],@t[1] + add @x[4],@x[4],#3 @ counter+3 + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] + ldr @t[3],[sp,#4*(32+2)] @ re-load len +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + stmia @t[0],{@x[0]-@x[7]} + add @t[2],sp,#4*(0) + sub @t[3],@t[3],#64*3 @ len-=64*3 + +.Loop_tail_neon: + ldrb @t[0],[@t[2]],#1 @ read buffer on stack + ldrb @t[1],[r12],#1 @ read input + subs @t[3],@t[3],#1 + eor @t[0],@t[0],@t[1] + strb @t[0],[r14],#1 @ store ouput + bne .Loop_tail_neon + +.Ldone_neon: + add sp,sp,#4*(32+4) + vldmia sp,{d8-d15} + add sp,sp,#4*(16+3) + ldmia sp!,{r4-r11,pc} +.size ChaCha20_neon,.-ChaCha20_neon +.comm OPENSSL_armcap_P,4,4 +#endif +___ +}}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/chacha/asm/chacha-armv8.pl b/external/boringssl/crypto/chacha/asm/chacha-armv8.pl new file mode 100755 index 0000000000..215d9657a1 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-armv8.pl @@ -0,0 +1,1127 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 2015 +# +# ChaCha20 for ARMv8. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU +# +# Apple A7 5.50/+49% 3.33 1.70 +# Cortex-A53 8.40/+80% 4.72 4.72(*) +# Cortex-A57 8.06/+43% 4.90 4.43(**) +# Denver 4.50/+82% 2.63 2.67(*) +# X-Gene 9.50/+46% 8.82 8.89(*) +# +# (*) it's expected that doubling interleave factor doesn't help +# all processors, only those with higher NEON latency and +# higher instruction issue rate; +# (**) expected improvement was actually higher; + +$flavour=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +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"; +} + +my ($out,$inp,$len,$key,$ctr) = map("x$_",(0..4)); + +my @x=map("x$_",(5..17,19..21)); +my @d=map("x$_",(22..28,30)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); + + ( + "&add_32 (@x[$a0],@x[$a0],@x[$b0])", + "&add_32 (@x[$a1],@x[$a1],@x[$b1])", + "&add_32 (@x[$a2],@x[$a2],@x[$b2])", + "&add_32 (@x[$a3],@x[$a3],@x[$b3])", + "&eor_32 (@x[$d0],@x[$d0],@x[$a0])", + "&eor_32 (@x[$d1],@x[$d1],@x[$a1])", + "&eor_32 (@x[$d2],@x[$d2],@x[$a2])", + "&eor_32 (@x[$d3],@x[$d3],@x[$a3])", + "&ror_32 (@x[$d0],@x[$d0],16)", + "&ror_32 (@x[$d1],@x[$d1],16)", + "&ror_32 (@x[$d2],@x[$d2],16)", + "&ror_32 (@x[$d3],@x[$d3],16)", + + "&add_32 (@x[$c0],@x[$c0],@x[$d0])", + "&add_32 (@x[$c1],@x[$c1],@x[$d1])", + "&add_32 (@x[$c2],@x[$c2],@x[$d2])", + "&add_32 (@x[$c3],@x[$c3],@x[$d3])", + "&eor_32 (@x[$b0],@x[$b0],@x[$c0])", + "&eor_32 (@x[$b1],@x[$b1],@x[$c1])", + "&eor_32 (@x[$b2],@x[$b2],@x[$c2])", + "&eor_32 (@x[$b3],@x[$b3],@x[$c3])", + "&ror_32 (@x[$b0],@x[$b0],20)", + "&ror_32 (@x[$b1],@x[$b1],20)", + "&ror_32 (@x[$b2],@x[$b2],20)", + "&ror_32 (@x[$b3],@x[$b3],20)", + + "&add_32 (@x[$a0],@x[$a0],@x[$b0])", + "&add_32 (@x[$a1],@x[$a1],@x[$b1])", + "&add_32 (@x[$a2],@x[$a2],@x[$b2])", + "&add_32 (@x[$a3],@x[$a3],@x[$b3])", + "&eor_32 (@x[$d0],@x[$d0],@x[$a0])", + "&eor_32 (@x[$d1],@x[$d1],@x[$a1])", + "&eor_32 (@x[$d2],@x[$d2],@x[$a2])", + "&eor_32 (@x[$d3],@x[$d3],@x[$a3])", + "&ror_32 (@x[$d0],@x[$d0],24)", + "&ror_32 (@x[$d1],@x[$d1],24)", + "&ror_32 (@x[$d2],@x[$d2],24)", + "&ror_32 (@x[$d3],@x[$d3],24)", + + "&add_32 (@x[$c0],@x[$c0],@x[$d0])", + "&add_32 (@x[$c1],@x[$c1],@x[$d1])", + "&add_32 (@x[$c2],@x[$c2],@x[$d2])", + "&add_32 (@x[$c3],@x[$c3],@x[$d3])", + "&eor_32 (@x[$b0],@x[$b0],@x[$c0])", + "&eor_32 (@x[$b1],@x[$b1],@x[$c1])", + "&eor_32 (@x[$b2],@x[$b2],@x[$c2])", + "&eor_32 (@x[$b3],@x[$b3],@x[$c3])", + "&ror_32 (@x[$b0],@x[$b0],25)", + "&ror_32 (@x[$b1],@x[$b1],25)", + "&ror_32 (@x[$b2],@x[$b2],25)", + "&ror_32 (@x[$b3],@x[$b3],25)" + ); +} + +$code.=<<___; +#include + +.text + +.extern OPENSSL_armcap_P + +.align 5 +.Lsigma: +.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral +.Lone: +.long 1,0,0,0 +.LOPENSSL_armcap_P: +#ifdef __ILP32__ +.long OPENSSL_armcap_P-. +#else +.quad OPENSSL_armcap_P-. +#endif +.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by " + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,%function +.align 5 +ChaCha20_ctr32: + cbz $len,.Labort + adr @x[0],.LOPENSSL_armcap_P + cmp $len,#192 + b.lo .Lshort +#ifdef __ILP32__ + ldrsw @x[1],[@x[0]] +#else + ldr @x[1],[@x[0]] +#endif + ldr w17,[@x[1],@x[0]] + tst w17,#ARMV7_NEON + b.ne ChaCha20_neon + +.Lshort: + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + 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,#64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ldp @d[6],@d[7],[$ctr] // load counter +#ifdef __ARMEB__ + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + +.Loop_outer: + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + mov.32 @x[6],@d[3] + lsr @x[7],@d[3],#32 + mov.32 @x[8],@d[4] + lsr @x[9],@d[4],#32 + mov.32 @x[10],@d[5] + lsr @x[11],@d[5],#32 + mov.32 @x[12],@d[6] + lsr @x[13],@d[6],#32 + mov.32 @x[14],@d[7] + lsr @x[15],@d[7],#32 + + mov $ctr,#10 + subs $len,$len,#64 +.Loop: + sub $ctr,$ctr,#1 +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + cbnz $ctr,.Loop + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add @x[1],@x[1],@d[0],lsr#32 + add.32 @x[2],@x[2],@d[1] + add @x[3],@x[3],@d[1],lsr#32 + add.32 @x[4],@x[4],@d[2] + add @x[5],@x[5],@d[2],lsr#32 + add.32 @x[6],@x[6],@d[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add @x[15],@x[15],@d[7],lsr#32 + + b.lo .Ltail + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#1 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + + b.hi .Loop_outer + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 +.Labort: + ret + +.align 4 +.Ltail: + add $len,$len,#64 +.Less_than_64: + sub $out,$out,#1 + add $inp,$inp,$len + add $out,$out,$len + add $ctr,sp,$len + neg $len,$len + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + stp @x[0],@x[2],[sp,#0] + stp @x[4],@x[6],[sp,#16] + stp @x[8],@x[10],[sp,#32] + stp @x[12],@x[14],[sp,#48] + +.Loop_tail: + ldrb w10,[$inp,$len] + ldrb w11,[$ctr,$len] + add $len,$len,#1 + eor w10,w10,w11 + strb w10,[$out,$len] + cbnz $len,.Loop_tail + + stp xzr,xzr,[sp,#0] + stp xzr,xzr,[sp,#16] + stp xzr,xzr,[sp,#32] + stp xzr,xzr,[sp,#48] + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +{{{ +my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) = + map("v$_.4s",(0..7,16..23)); +my (@K)=map("v$_.4s",(24..30)); +my $ONE="v31.4s"; + +sub NEONROUND { +my $odd = pop; +my ($a,$b,$c,$d,$t)=@_; + + ( + "&add ('$a','$a','$b')", + "&eor ('$d','$d','$a')", + "&rev32_16 ('$d','$d')", # vrot ($d,16) + + "&add ('$c','$c','$d')", + "&eor ('$t','$b','$c')", + "&ushr ('$b','$t',20)", + "&sli ('$b','$t',12)", + + "&add ('$a','$a','$b')", + "&eor ('$t','$d','$a')", + "&ushr ('$d','$t',24)", + "&sli ('$d','$t',8)", + + "&add ('$c','$c','$d')", + "&eor ('$t','$b','$c')", + "&ushr ('$b','$t',25)", + "&sli ('$b','$t',7)", + + "&ext ('$c','$c','$c',8)", + "&ext ('$d','$d','$d',$odd?4:12)", + "&ext ('$b','$b','$b',$odd?12:4)" + ); +} + +$code.=<<___; + +.type ChaCha20_neon,%function +.align 5 +ChaCha20_neon: + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + 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] + cmp $len,#512 + b.hs .L512_or_more_neon + + sub sp,sp,#64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ld1 {@K[0]},[@x[0]],#16 + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] + ld1 {$ONE},[@x[0]] +#ifdef __ARMEB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + add @K[3],@K[3],$ONE // += 1 + add @K[4],@K[3],$ONE + add @K[5],@K[4],$ONE + shl $ONE,$ONE,#2 // 1 -> 4 + +.Loop_outer_neon: + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + mov $A0,@K[0] + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + mov $A1,@K[0] + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + mov $A2,@K[0] + mov.32 @x[6],@d[3] + mov $B0,@K[1] + lsr @x[7],@d[3],#32 + mov $B1,@K[1] + mov.32 @x[8],@d[4] + mov $B2,@K[1] + lsr @x[9],@d[4],#32 + mov $D0,@K[3] + mov.32 @x[10],@d[5] + mov $D1,@K[4] + lsr @x[11],@d[5],#32 + mov $D2,@K[5] + mov.32 @x[12],@d[6] + mov $C0,@K[2] + lsr @x[13],@d[6],#32 + mov $C1,@K[2] + mov.32 @x[14],@d[7] + mov $C2,@K[2] + lsr @x[15],@d[7],#32 + + mov $ctr,#10 + subs $len,$len,#256 +.Loop_neon: + sub $ctr,$ctr,#1 +___ + my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + my @thread3=&ROUND(0,4,8,12); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&ROUND(0,5,10,15); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } +$code.=<<___; + cbnz $ctr,.Loop_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add $A0,$A0,@K[0] + add @x[1],@x[1],@d[0],lsr#32 + add $A1,$A1,@K[0] + add.32 @x[2],@x[2],@d[1] + add $A2,$A2,@K[0] + add @x[3],@x[3],@d[1],lsr#32 + add $C0,$C0,@K[2] + add.32 @x[4],@x[4],@d[2] + add $C1,$C1,@K[2] + add @x[5],@x[5],@d[2],lsr#32 + add $C2,$C2,@K[2] + add.32 @x[6],@x[6],@d[3] + add $D0,$D0,@K[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add $D1,$D1,@K[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add $D2,$D2,@K[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add $B0,$B0,@K[1] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add $B1,$B1,@K[1] + add @x[15],@x[15],@d[7],lsr#32 + add $B2,$B2,@K[1] + + b.lo .Ltail_neon + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + ld1.8 {$T0-$T3},[$inp],#64 + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor $A0,$A0,$T0 + eor @x[10],@x[10],@x[11] + eor $B0,$B0,$T1 + eor @x[12],@x[12],@x[13] + eor $C0,$C0,$T2 + eor @x[14],@x[14],@x[15] + eor $D0,$D0,$T3 + ld1.8 {$T0-$T3},[$inp],#64 + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#4 // increment counter + stp @x[4],@x[6],[$out,#16] + add @K[3],@K[3],$ONE // += 4 + stp @x[8],@x[10],[$out,#32] + add @K[4],@K[4],$ONE + stp @x[12],@x[14],[$out,#48] + add @K[5],@K[5],$ONE + add $out,$out,#64 + + st1.8 {$A0-$D0},[$out],#64 + ld1.8 {$A0-$D0},[$inp],#64 + + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + + eor $A2,$A2,$A0 + eor $B2,$B2,$B0 + eor $C2,$C2,$C0 + eor $D2,$D2,$D0 + st1.8 {$A2-$D2},[$out],#64 + + b.hi .Loop_outer_neon + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret + +.Ltail_neon: + add $len,$len,#256 + cmp $len,#64 + b.lo .Less_than_64 + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#4 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + b.eq .Ldone_neon + sub $len,$len,#64 + cmp $len,#64 + b.lo .Less_than_128 + + ld1.8 {$T0-$T3},[$inp],#64 + eor $A0,$A0,$T0 + eor $B0,$B0,$T1 + eor $C0,$C0,$T2 + eor $D0,$D0,$T3 + st1.8 {$A0-$D0},[$out],#64 + b.eq .Ldone_neon + sub $len,$len,#64 + cmp $len,#64 + b.lo .Less_than_192 + + ld1.8 {$T0-$T3},[$inp],#64 + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + b.eq .Ldone_neon + sub $len,$len,#64 + + st1.8 {$A2-$D2},[sp] + b .Last_neon + +.Less_than_128: + st1.8 {$A0-$D0},[sp] + b .Last_neon +.Less_than_192: + st1.8 {$A1-$D1},[sp] + b .Last_neon + +.align 4 +.Last_neon: + sub $out,$out,#1 + add $inp,$inp,$len + add $out,$out,$len + add $ctr,sp,$len + neg $len,$len + +.Loop_tail_neon: + ldrb w10,[$inp,$len] + ldrb w11,[$ctr,$len] + add $len,$len,#1 + eor w10,w10,w11 + strb w10,[$out,$len] + cbnz $len,.Loop_tail_neon + + stp xzr,xzr,[sp,#0] + stp xzr,xzr,[sp,#16] + stp xzr,xzr,[sp,#32] + stp xzr,xzr,[sp,#48] + +.Ldone_neon: + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret +.size ChaCha20_neon,.-ChaCha20_neon +___ +{ +my ($T0,$T1,$T2,$T3,$T4,$T5)=@K; +my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2, + $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23)); + +$code.=<<___; +.type ChaCha20_512_neon,%function +.align 5 +ChaCha20_512_neon: + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + 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] + +.L512_or_more_neon: + sub sp,sp,#128+64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ld1 {@K[0]},[@x[0]],#16 + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] + ld1 {$ONE},[@x[0]] +#ifdef __ARMEB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + add @K[3],@K[3],$ONE // += 1 + stp @K[0],@K[1],[sp,#0] // off-load key block, invariant part + add @K[3],@K[3],$ONE // not typo + str @K[2],[sp,#32] + add @K[4],@K[3],$ONE + add @K[5],@K[4],$ONE + add @K[6],@K[5],$ONE + shl $ONE,$ONE,#2 // 1 -> 4 + + stp d8,d9,[sp,#128+0] // meet ABI requirements + stp d10,d11,[sp,#128+16] + stp d12,d13,[sp,#128+32] + stp d14,d15,[sp,#128+48] + + sub $len,$len,#512 // not typo + +.Loop_outer_512_neon: + mov $A0,@K[0] + mov $A1,@K[0] + mov $A2,@K[0] + mov $A3,@K[0] + mov $A4,@K[0] + mov $A5,@K[0] + mov $B0,@K[1] + mov.32 @x[0],@d[0] // unpack key block + mov $B1,@K[1] + lsr @x[1],@d[0],#32 + mov $B2,@K[1] + mov.32 @x[2],@d[1] + mov $B3,@K[1] + lsr @x[3],@d[1],#32 + mov $B4,@K[1] + mov.32 @x[4],@d[2] + mov $B5,@K[1] + lsr @x[5],@d[2],#32 + mov $D0,@K[3] + mov.32 @x[6],@d[3] + mov $D1,@K[4] + lsr @x[7],@d[3],#32 + mov $D2,@K[5] + mov.32 @x[8],@d[4] + mov $D3,@K[6] + lsr @x[9],@d[4],#32 + mov $C0,@K[2] + mov.32 @x[10],@d[5] + mov $C1,@K[2] + lsr @x[11],@d[5],#32 + add $D4,$D0,$ONE // +4 + mov.32 @x[12],@d[6] + add $D5,$D1,$ONE // +4 + lsr @x[13],@d[6],#32 + mov $C2,@K[2] + mov.32 @x[14],@d[7] + mov $C3,@K[2] + lsr @x[15],@d[7],#32 + mov $C4,@K[2] + stp @K[3],@K[4],[sp,#48] // off-load key block, variable part + mov $C5,@K[2] + str @K[5],[sp,#80] + + mov $ctr,#5 + subs $len,$len,#512 +.Loop_upper_neon: + sub $ctr,$ctr,#1 +___ + my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + my @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0); + my @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0); + my @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0); + my @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + my $diff = ($#thread0+1)*6 - $#thread67 - 1; + my $i = 0; + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } +$code.=<<___; + cbnz $ctr,.Loop_upper_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add @x[1],@x[1],@d[0],lsr#32 + add.32 @x[2],@x[2],@d[1] + add @x[3],@x[3],@d[1],lsr#32 + add.32 @x[4],@x[4],@d[2] + add @x[5],@x[5],@d[2],lsr#32 + add.32 @x[6],@x[6],@d[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add @x[15],@x[15],@d[7],lsr#32 + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#1 // increment counter + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + stp @x[4],@x[6],[$out,#16] + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + stp @x[8],@x[10],[$out,#32] + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + mov.32 @x[6],@d[3] + lsr @x[7],@d[3],#32 + mov.32 @x[8],@d[4] + lsr @x[9],@d[4],#32 + mov.32 @x[10],@d[5] + lsr @x[11],@d[5],#32 + mov.32 @x[12],@d[6] + lsr @x[13],@d[6],#32 + mov.32 @x[14],@d[7] + lsr @x[15],@d[7],#32 + + mov $ctr,#5 +.Loop_lower_neon: + sub $ctr,$ctr,#1 +___ + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } +$code.=<<___; + cbnz $ctr,.Loop_lower_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + ldp @K[0],@K[1],[sp,#0] + add @x[1],@x[1],@d[0],lsr#32 + ldp @K[2],@K[3],[sp,#32] + add.32 @x[2],@x[2],@d[1] + ldp @K[4],@K[5],[sp,#64] + add @x[3],@x[3],@d[1],lsr#32 + add $A0,$A0,@K[0] + add.32 @x[4],@x[4],@d[2] + add $A1,$A1,@K[0] + add @x[5],@x[5],@d[2],lsr#32 + add $A2,$A2,@K[0] + add.32 @x[6],@x[6],@d[3] + add $A3,$A3,@K[0] + add @x[7],@x[7],@d[3],lsr#32 + add $A4,$A4,@K[0] + add.32 @x[8],@x[8],@d[4] + add $A5,$A5,@K[0] + add @x[9],@x[9],@d[4],lsr#32 + add $C0,$C0,@K[2] + add.32 @x[10],@x[10],@d[5] + add $C1,$C1,@K[2] + add @x[11],@x[11],@d[5],lsr#32 + add $C2,$C2,@K[2] + add.32 @x[12],@x[12],@d[6] + add $C3,$C3,@K[2] + add @x[13],@x[13],@d[6],lsr#32 + add $C4,$C4,@K[2] + add.32 @x[14],@x[14],@d[7] + add $C5,$C5,@K[2] + add @x[15],@x[15],@d[7],lsr#32 + add $D4,$D4,$ONE // +4 + add @x[0],@x[0],@x[1],lsl#32 // pack + add $D5,$D5,$ONE // +4 + add @x[2],@x[2],@x[3],lsl#32 + add $D0,$D0,@K[3] + ldp @x[1],@x[3],[$inp,#0] // load input + add $D1,$D1,@K[4] + add @x[4],@x[4],@x[5],lsl#32 + add $D2,$D2,@K[5] + add @x[6],@x[6],@x[7],lsl#32 + add $D3,$D3,@K[6] + ldp @x[5],@x[7],[$inp,#16] + add $D4,$D4,@K[3] + add @x[8],@x[8],@x[9],lsl#32 + add $D5,$D5,@K[4] + add @x[10],@x[10],@x[11],lsl#32 + add $B0,$B0,@K[1] + ldp @x[9],@x[11],[$inp,#32] + add $B1,$B1,@K[1] + add @x[12],@x[12],@x[13],lsl#32 + add $B2,$B2,@K[1] + add @x[14],@x[14],@x[15],lsl#32 + add $B3,$B3,@K[1] + ldp @x[13],@x[15],[$inp,#48] + add $B4,$B4,@K[1] + add $inp,$inp,#64 + add $B5,$B5,@K[1] + +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + ld1.8 {$T0-$T3},[$inp],#64 + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor $A0,$A0,$T0 + eor @x[10],@x[10],@x[11] + eor $B0,$B0,$T1 + eor @x[12],@x[12],@x[13] + eor $C0,$C0,$T2 + eor @x[14],@x[14],@x[15] + eor $D0,$D0,$T3 + ld1.8 {$T0-$T3},[$inp],#64 + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#7 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + st1.8 {$A0-$D0},[$out],#64 + + ld1.8 {$A0-$D0},[$inp],#64 + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + + ld1.8 {$A1-$D1},[$inp],#64 + eor $A2,$A2,$A0 + ldp @K[0],@K[1],[sp,#0] + eor $B2,$B2,$B0 + ldp @K[2],@K[3],[sp,#32] + eor $C2,$C2,$C0 + eor $D2,$D2,$D0 + st1.8 {$A2-$D2},[$out],#64 + + ld1.8 {$A2-$D2},[$inp],#64 + eor $A3,$A3,$A1 + eor $B3,$B3,$B1 + eor $C3,$C3,$C1 + eor $D3,$D3,$D1 + st1.8 {$A3-$D3},[$out],#64 + + ld1.8 {$A3-$D3},[$inp],#64 + eor $A4,$A4,$A2 + eor $B4,$B4,$B2 + eor $C4,$C4,$C2 + eor $D4,$D4,$D2 + st1.8 {$A4-$D4},[$out],#64 + + shl $A0,$ONE,#1 // 4 -> 8 + eor $A5,$A5,$A3 + eor $B5,$B5,$B3 + eor $C5,$C5,$C3 + eor $D5,$D5,$D3 + st1.8 {$A5-$D5},[$out],#64 + + add @K[3],@K[3],$A0 // += 8 + add @K[4],@K[4],$A0 + add @K[5],@K[5],$A0 + add @K[6],@K[6],$A0 + + b.hs .Loop_outer_512_neon + + adds $len,$len,#512 + ushr $A0,$ONE,#2 // 4 -> 1 + + ldp d8,d9,[sp,#128+0] // meet ABI requirements + ldp d10,d11,[sp,#128+16] + ldp d12,d13,[sp,#128+32] + ldp d14,d15,[sp,#128+48] + + stp @K[0],$ONE,[sp,#0] // wipe off-load area + stp @K[0],$ONE,[sp,#32] + stp @K[0],$ONE,[sp,#64] + + b.eq .Ldone_512_neon + + cmp $len,#192 + sub @K[3],@K[3],$A0 // -= 1 + sub @K[4],@K[4],$A0 + sub @K[5],@K[5],$A0 + add sp,sp,#128 + b.hs .Loop_outer_neon + + eor @K[1],@K[1],@K[1] + eor @K[2],@K[2],@K[2] + eor @K[3],@K[3],@K[3] + eor @K[4],@K[4],@K[4] + eor @K[5],@K[5],@K[5] + eor @K[6],@K[6],@K[6] + b .Loop_outer + +.Ldone_512_neon: + ldp x19,x20,[x29,#16] + add sp,sp,#128+64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret +.size ChaCha20_512_neon,.-ChaCha20_512_neon +___ +} +}}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + (s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or + (m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or + (s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or + (m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or + (s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1)); + + #s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; + + print $_,"\n"; +} +close STDOUT; # flush diff --git a/external/boringssl/crypto/chacha/asm/chacha-x86.pl b/external/boringssl/crypto/chacha/asm/chacha-x86.pl new file mode 100755 index 0000000000..edce43dce5 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-x86.pl @@ -0,0 +1,753 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 2015 +# +# ChaCha20 for x86. +# +# Performance in cycles per byte out of large buffer. +# +# 1xIALU/gcc 4xSSSE3 +# Pentium 17.5/+80% +# PIII 14.2/+60% +# P4 18.6/+84% +# Core2 9.56/+89% 4.83 +# Westmere 9.50/+45% 3.35 +# Sandy Bridge 10.5/+47% 3.20 +# Haswell 8.15/+50% 2.83 +# Silvermont 17.4/+36% 8.35 +# Sledgehammer 10.2/+54% +# Bulldozer 13.4/+50% 4.38(*) +# +# (*) Bulldozer actually executes 4xXOP code path that delivers 3.55; +# +# Modified from upstream OpenSSL to remove the XOP code. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386"); + +$xmm=$ymm=0; +for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); } + +$ymm=$xmm; + +$a="eax"; +($b,$b_)=("ebx","ebp"); +($c,$c_)=("ecx","esi"); +($d,$d_)=("edx","edi"); + +sub QUARTERROUND { +my ($ai,$bi,$ci,$di,$i)=@_; +my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next +my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous + + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + + if ($i==0) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==3) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn)); + } elsif ($i==4) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==7) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn)); + } + + #&add ($a,$b); # see elsewhere + &xor ($d,$a); + &mov (&DWP(4*$cp,"esp"),$c_) if ($ai>0 && $ai<3); + &rol ($d,16); + &mov (&DWP(4*$bp,"esp"),$b_) if ($i!=0); + &add ($c,$d); + &mov ($c_,&DWP(4*$cn,"esp")) if ($ai>0 && $ai<3); + &xor ($b,$c); + &mov ($d_,&DWP(4*$dn,"esp")) if ($di!=$dn); + &rol ($b,12); + &mov ($b_,&DWP(4*$bn,"esp")) if ($i<7); + &mov ($b_,&DWP(128,"esp")) if ($i==7); # loop counter + &add ($a,$b); + &xor ($d,$a); + &mov (&DWP(4*$ai,"esp"),$a); + &rol ($d,8); + &mov ($a,&DWP(4*$an,"esp")); + &add ($c,$d); + &mov (&DWP(4*$di,"esp"),$d) if ($di!=$dn); + &mov ($d_,$d) if ($di==$dn); + &xor ($b,$c); + &add ($a,$b_) if ($i<7); # elsewhere + &rol ($b,7); + + ($b,$b_)=($b_,$b); + ($c,$c_)=($c_,$c); + ($d,$d_)=($d_,$d); +} + +&static_label("ssse3_shortcut"); +&static_label("ssse3_data"); +&static_label("pic_point"); + +&function_begin("ChaCha20_ctr32"); + &xor ("eax","eax"); + &cmp ("eax",&wparam(2)); # len==0? + &je (&label("no_data")); +if ($xmm) { + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("eax"); + &picmeup("ebp","OPENSSL_ia32cap_P","eax",&label("pic_point")); + &test (&DWP(0,"ebp"),1<<24); # test FXSR bit + &jz (&label("x86")); + &test (&DWP(4,"ebp"),1<<9); # test SSSE3 bit + &jz (&label("x86")); + &jmp (&label("ssse3_shortcut")); +&set_label("x86"); +} + &mov ("esi",&wparam(3)); # key + &mov ("edi",&wparam(4)); # counter and nonce + + &stack_push(33); + + &mov ("eax",&DWP(4*0,"esi")); # copy key + &mov ("ebx",&DWP(4*1,"esi")); + &mov ("ecx",&DWP(4*2,"esi")); + &mov ("edx",&DWP(4*3,"esi")); + &mov (&DWP(64+4*4,"esp"),"eax"); + &mov (&DWP(64+4*5,"esp"),"ebx"); + &mov (&DWP(64+4*6,"esp"),"ecx"); + &mov (&DWP(64+4*7,"esp"),"edx"); + &mov ("eax",&DWP(4*4,"esi")); + &mov ("ebx",&DWP(4*5,"esi")); + &mov ("ecx",&DWP(4*6,"esi")); + &mov ("edx",&DWP(4*7,"esi")); + &mov (&DWP(64+4*8,"esp"),"eax"); + &mov (&DWP(64+4*9,"esp"),"ebx"); + &mov (&DWP(64+4*10,"esp"),"ecx"); + &mov (&DWP(64+4*11,"esp"),"edx"); + &mov ("eax",&DWP(4*0,"edi")); # copy counter and nonce + &mov ("ebx",&DWP(4*1,"edi")); + &mov ("ecx",&DWP(4*2,"edi")); + &mov ("edx",&DWP(4*3,"edi")); + &sub ("eax",1); + &mov (&DWP(64+4*12,"esp"),"eax"); + &mov (&DWP(64+4*13,"esp"),"ebx"); + &mov (&DWP(64+4*14,"esp"),"ecx"); + &mov (&DWP(64+4*15,"esp"),"edx"); + &jmp (&label("entry")); + +&set_label("outer_loop",16); + &mov (&wparam(1),$b); # save input + &mov (&wparam(0),$a); # save output + &mov (&wparam(2),$c); # save len +&set_label("entry"); + &mov ($a,0x61707865); + &mov (&DWP(4*1,"esp"),0x3320646e); + &mov (&DWP(4*2,"esp"),0x79622d32); + &mov (&DWP(4*3,"esp"),0x6b206574); + + &mov ($b, &DWP(64+4*5,"esp")); # copy key material + &mov ($b_,&DWP(64+4*6,"esp")); + &mov ($c, &DWP(64+4*10,"esp")); + &mov ($c_,&DWP(64+4*11,"esp")); + &mov ($d, &DWP(64+4*13,"esp")); + &mov ($d_,&DWP(64+4*14,"esp")); + &mov (&DWP(4*5,"esp"),$b); + &mov (&DWP(4*6,"esp"),$b_); + &mov (&DWP(4*10,"esp"),$c); + &mov (&DWP(4*11,"esp"),$c_); + &mov (&DWP(4*13,"esp"),$d); + &mov (&DWP(4*14,"esp"),$d_); + + &mov ($b, &DWP(64+4*7,"esp")); + &mov ($d_,&DWP(64+4*15,"esp")); + &mov ($d, &DWP(64+4*12,"esp")); + &mov ($b_,&DWP(64+4*4,"esp")); + &mov ($c, &DWP(64+4*8,"esp")); + &mov ($c_,&DWP(64+4*9,"esp")); + &add ($d,1); # counter value + &mov (&DWP(4*7,"esp"),$b); + &mov (&DWP(4*15,"esp"),$d_); + &mov (&DWP(64+4*12,"esp"),$d); # save counter value + + &mov ($b,10); # loop counter + &jmp (&label("loop")); + +&set_label("loop",16); + &add ($a,$b_); # elsewhere + &mov (&DWP(128,"esp"),$b); # save loop counter + &mov ($b,$b_); + &QUARTERROUND(0, 4, 8, 12, 0); + &QUARTERROUND(1, 5, 9, 13, 1); + &QUARTERROUND(2, 6,10, 14, 2); + &QUARTERROUND(3, 7,11, 15, 3); + &QUARTERROUND(0, 5,10, 15, 4); + &QUARTERROUND(1, 6,11, 12, 5); + &QUARTERROUND(2, 7, 8, 13, 6); + &QUARTERROUND(3, 4, 9, 14, 7); + &dec ($b); + &jnz (&label("loop")); + + &mov ($b,&wparam(2)); # load len + + &add ($a,0x61707865); # accumulate key material + &add ($b_,&DWP(64+4*4,"esp")); + &add ($c, &DWP(64+4*8,"esp")); + &add ($c_,&DWP(64+4*9,"esp")); + + &cmp ($b,64); + &jb (&label("tail")); + + &mov ($b,&wparam(1)); # load input pointer + &add ($d, &DWP(64+4*12,"esp")); + &add ($d_,&DWP(64+4*14,"esp")); + + &xor ($a, &DWP(4*0,$b)); # xor with input + &xor ($b_,&DWP(4*4,$b)); + &mov (&DWP(4*0,"esp"),$a); + &mov ($a,&wparam(0)); # load output pointer + &xor ($c, &DWP(4*8,$b)); + &xor ($c_,&DWP(4*9,$b)); + &xor ($d, &DWP(4*12,$b)); + &xor ($d_,&DWP(4*14,$b)); + &mov (&DWP(4*4,$a),$b_); # write output + &mov (&DWP(4*8,$a),$c); + &mov (&DWP(4*9,$a),$c_); + &mov (&DWP(4*12,$a),$d); + &mov (&DWP(4*14,$a),$d_); + + &mov ($b_,&DWP(4*1,"esp")); + &mov ($c, &DWP(4*2,"esp")); + &mov ($c_,&DWP(4*3,"esp")); + &mov ($d, &DWP(4*5,"esp")); + &mov ($d_,&DWP(4*6,"esp")); + &add ($b_,0x3320646e); # accumulate key material + &add ($c, 0x79622d32); + &add ($c_,0x6b206574); + &add ($d, &DWP(64+4*5,"esp")); + &add ($d_,&DWP(64+4*6,"esp")); + &xor ($b_,&DWP(4*1,$b)); + &xor ($c, &DWP(4*2,$b)); + &xor ($c_,&DWP(4*3,$b)); + &xor ($d, &DWP(4*5,$b)); + &xor ($d_,&DWP(4*6,$b)); + &mov (&DWP(4*1,$a),$b_); + &mov (&DWP(4*2,$a),$c); + &mov (&DWP(4*3,$a),$c_); + &mov (&DWP(4*5,$a),$d); + &mov (&DWP(4*6,$a),$d_); + + &mov ($b_,&DWP(4*7,"esp")); + &mov ($c, &DWP(4*10,"esp")); + &mov ($c_,&DWP(4*11,"esp")); + &mov ($d, &DWP(4*13,"esp")); + &mov ($d_,&DWP(4*15,"esp")); + &add ($b_,&DWP(64+4*7,"esp")); + &add ($c, &DWP(64+4*10,"esp")); + &add ($c_,&DWP(64+4*11,"esp")); + &add ($d, &DWP(64+4*13,"esp")); + &add ($d_,&DWP(64+4*15,"esp")); + &xor ($b_,&DWP(4*7,$b)); + &xor ($c, &DWP(4*10,$b)); + &xor ($c_,&DWP(4*11,$b)); + &xor ($d, &DWP(4*13,$b)); + &xor ($d_,&DWP(4*15,$b)); + &lea ($b,&DWP(4*16,$b)); + &mov (&DWP(4*7,$a),$b_); + &mov ($b_,&DWP(4*0,"esp")); + &mov (&DWP(4*10,$a),$c); + &mov ($c,&wparam(2)); # len + &mov (&DWP(4*11,$a),$c_); + &mov (&DWP(4*13,$a),$d); + &mov (&DWP(4*15,$a),$d_); + &mov (&DWP(4*0,$a),$b_); + &lea ($a,&DWP(4*16,$a)); + &sub ($c,64); + &jnz (&label("outer_loop")); + + &jmp (&label("done")); + +&set_label("tail"); + &add ($d, &DWP(64+4*12,"esp")); + &add ($d_,&DWP(64+4*14,"esp")); + &mov (&DWP(4*0,"esp"),$a); + &mov (&DWP(4*4,"esp"),$b_); + &mov (&DWP(4*8,"esp"),$c); + &mov (&DWP(4*9,"esp"),$c_); + &mov (&DWP(4*12,"esp"),$d); + &mov (&DWP(4*14,"esp"),$d_); + + &mov ($b_,&DWP(4*1,"esp")); + &mov ($c, &DWP(4*2,"esp")); + &mov ($c_,&DWP(4*3,"esp")); + &mov ($d, &DWP(4*5,"esp")); + &mov ($d_,&DWP(4*6,"esp")); + &add ($b_,0x3320646e); # accumulate key material + &add ($c, 0x79622d32); + &add ($c_,0x6b206574); + &add ($d, &DWP(64+4*5,"esp")); + &add ($d_,&DWP(64+4*6,"esp")); + &mov (&DWP(4*1,"esp"),$b_); + &mov (&DWP(4*2,"esp"),$c); + &mov (&DWP(4*3,"esp"),$c_); + &mov (&DWP(4*5,"esp"),$d); + &mov (&DWP(4*6,"esp"),$d_); + + &mov ($b_,&DWP(4*7,"esp")); + &mov ($c, &DWP(4*10,"esp")); + &mov ($c_,&DWP(4*11,"esp")); + &mov ($d, &DWP(4*13,"esp")); + &mov ($d_,&DWP(4*15,"esp")); + &add ($b_,&DWP(64+4*7,"esp")); + &add ($c, &DWP(64+4*10,"esp")); + &add ($c_,&DWP(64+4*11,"esp")); + &add ($d, &DWP(64+4*13,"esp")); + &add ($d_,&DWP(64+4*15,"esp")); + &mov (&DWP(4*7,"esp"),$b_); + &mov ($b_,&wparam(1)); # load input + &mov (&DWP(4*10,"esp"),$c); + &mov ($c,&wparam(0)); # load output + &mov (&DWP(4*11,"esp"),$c_); + &xor ($c_,$c_); + &mov (&DWP(4*13,"esp"),$d); + &mov (&DWP(4*15,"esp"),$d_); + + &xor ("eax","eax"); + &xor ("edx","edx"); +&set_label("tail_loop"); + &movb ("al",&BP(0,$c_,$b_)); + &movb ("dl",&BP(0,"esp",$c_)); + &lea ($c_,&DWP(1,$c_)); + &xor ("al","dl"); + &mov (&BP(-1,$c,$c_),"al"); + &dec ($b); + &jnz (&label("tail_loop")); + +&set_label("done"); + &stack_pop(33); +&set_label("no_data"); +&function_end("ChaCha20_ctr32"); + +if ($xmm) { +my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7)); +my ($out,$inp,$len)=("edi","esi","ecx"); + +sub QUARTERROUND_SSSE3 { +my ($ai,$bi,$ci,$di,$i)=@_; +my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next +my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous + + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + + if ($i==0) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==3) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn)); + } elsif ($i==4) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==7) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn)); + } + + #&paddd ($xa,$xb); # see elsewhere + #&pxor ($xd,$xa); # see elsewhere + &movdqa(&QWP(16*$cp-128,"ebx"),$xc_) if ($ai>0 && $ai<3); + &pshufb ($xd,&QWP(0,"eax")); # rot16 + &movdqa(&QWP(16*$bp-128,"ebx"),$xb_) if ($i!=0); + &paddd ($xc,$xd); + &movdqa($xc_,&QWP(16*$cn-128,"ebx")) if ($ai>0 && $ai<3); + &pxor ($xb,$xc); + &movdqa($xb_,&QWP(16*$bn-128,"ebx")) if ($i<7); + &movdqa ($xa_,$xb); # borrow as temporary + &pslld ($xb,12); + &psrld ($xa_,20); + &por ($xb,$xa_); + &movdqa($xa_,&QWP(16*$an-128,"ebx")); + &paddd ($xa,$xb); + &movdqa($xd_,&QWP(16*$dn-128,"ebx")) if ($di!=$dn); + &pxor ($xd,$xa); + &movdqa (&QWP(16*$ai-128,"ebx"),$xa); + &pshufb ($xd,&QWP(16,"eax")); # rot8 + &paddd ($xc,$xd); + &movdqa (&QWP(16*$di-128,"ebx"),$xd) if ($di!=$dn); + &movdqa ($xd_,$xd) if ($di==$dn); + &pxor ($xb,$xc); + &paddd ($xa_,$xb_) if ($i<7); # elsewhere + &movdqa ($xa,$xb); # borrow as temporary + &pslld ($xb,7); + &psrld ($xa,25); + &pxor ($xd_,$xa_) if ($i<7); # elsewhere + &por ($xb,$xa); + + ($xa,$xa_)=($xa_,$xa); + ($xb,$xb_)=($xb_,$xb); + ($xc,$xc_)=($xc_,$xc); + ($xd,$xd_)=($xd_,$xd); +} + +&function_begin("ChaCha20_ssse3"); +&set_label("ssse3_shortcut"); + &mov ($out,&wparam(0)); + &mov ($inp,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ("edx",&wparam(3)); # key + &mov ("ebx",&wparam(4)); # counter and nonce + + &mov ("ebp","esp"); + &stack_push (131); + &and ("esp",-64); + &mov (&DWP(512,"esp"),"ebp"); + + &lea ("eax",&DWP(&label("ssse3_data")."-". + &label("pic_point"),"eax")); + &movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce + + &cmp ($len,64*4); + &jb (&label("1x")); + + &mov (&DWP(512+4,"esp"),"edx"); # offload pointers + &mov (&DWP(512+8,"esp"),"ebx"); + &sub ($len,64*4); # bias len + &lea ("ebp",&DWP(256+128,"esp")); # size optimization + + &movdqu ("xmm7",&QWP(0,"edx")); # key + &pshufd ("xmm0","xmm3",0x00); + &pshufd ("xmm1","xmm3",0x55); + &pshufd ("xmm2","xmm3",0xaa); + &pshufd ("xmm3","xmm3",0xff); + &paddd ("xmm0",&QWP(16*3,"eax")); # fix counters + &pshufd ("xmm4","xmm7",0x00); + &pshufd ("xmm5","xmm7",0x55); + &psubd ("xmm0",&QWP(16*4,"eax")); + &pshufd ("xmm6","xmm7",0xaa); + &pshufd ("xmm7","xmm7",0xff); + &movdqa (&QWP(16*12-128,"ebp"),"xmm0"); + &movdqa (&QWP(16*13-128,"ebp"),"xmm1"); + &movdqa (&QWP(16*14-128,"ebp"),"xmm2"); + &movdqa (&QWP(16*15-128,"ebp"),"xmm3"); + &movdqu ("xmm3",&QWP(16,"edx")); # key + &movdqa (&QWP(16*4-128,"ebp"),"xmm4"); + &movdqa (&QWP(16*5-128,"ebp"),"xmm5"); + &movdqa (&QWP(16*6-128,"ebp"),"xmm6"); + &movdqa (&QWP(16*7-128,"ebp"),"xmm7"); + &movdqa ("xmm7",&QWP(16*2,"eax")); # sigma + &lea ("ebx",&DWP(128,"esp")); # size optimization + + &pshufd ("xmm0","xmm3",0x00); + &pshufd ("xmm1","xmm3",0x55); + &pshufd ("xmm2","xmm3",0xaa); + &pshufd ("xmm3","xmm3",0xff); + &pshufd ("xmm4","xmm7",0x00); + &pshufd ("xmm5","xmm7",0x55); + &pshufd ("xmm6","xmm7",0xaa); + &pshufd ("xmm7","xmm7",0xff); + &movdqa (&QWP(16*8-128,"ebp"),"xmm0"); + &movdqa (&QWP(16*9-128,"ebp"),"xmm1"); + &movdqa (&QWP(16*10-128,"ebp"),"xmm2"); + &movdqa (&QWP(16*11-128,"ebp"),"xmm3"); + &movdqa (&QWP(16*0-128,"ebp"),"xmm4"); + &movdqa (&QWP(16*1-128,"ebp"),"xmm5"); + &movdqa (&QWP(16*2-128,"ebp"),"xmm6"); + &movdqa (&QWP(16*3-128,"ebp"),"xmm7"); + + &lea ($inp,&DWP(128,$inp)); # size optimization + &lea ($out,&DWP(128,$out)); # size optimization + &jmp (&label("outer_loop")); + +&set_label("outer_loop",16); + #&movdqa ("xmm0",&QWP(16*0-128,"ebp")); # copy key material + &movdqa ("xmm1",&QWP(16*1-128,"ebp")); + &movdqa ("xmm2",&QWP(16*2-128,"ebp")); + &movdqa ("xmm3",&QWP(16*3-128,"ebp")); + #&movdqa ("xmm4",&QWP(16*4-128,"ebp")); + &movdqa ("xmm5",&QWP(16*5-128,"ebp")); + &movdqa ("xmm6",&QWP(16*6-128,"ebp")); + &movdqa ("xmm7",&QWP(16*7-128,"ebp")); + #&movdqa (&QWP(16*0-128,"ebx"),"xmm0"); + &movdqa (&QWP(16*1-128,"ebx"),"xmm1"); + &movdqa (&QWP(16*2-128,"ebx"),"xmm2"); + &movdqa (&QWP(16*3-128,"ebx"),"xmm3"); + #&movdqa (&QWP(16*4-128,"ebx"),"xmm4"); + &movdqa (&QWP(16*5-128,"ebx"),"xmm5"); + &movdqa (&QWP(16*6-128,"ebx"),"xmm6"); + &movdqa (&QWP(16*7-128,"ebx"),"xmm7"); + #&movdqa ("xmm0",&QWP(16*8-128,"ebp")); + #&movdqa ("xmm1",&QWP(16*9-128,"ebp")); + &movdqa ("xmm2",&QWP(16*10-128,"ebp")); + &movdqa ("xmm3",&QWP(16*11-128,"ebp")); + &movdqa ("xmm4",&QWP(16*12-128,"ebp")); + &movdqa ("xmm5",&QWP(16*13-128,"ebp")); + &movdqa ("xmm6",&QWP(16*14-128,"ebp")); + &movdqa ("xmm7",&QWP(16*15-128,"ebp")); + &paddd ("xmm4",&QWP(16*4,"eax")); # counter value + #&movdqa (&QWP(16*8-128,"ebx"),"xmm0"); + #&movdqa (&QWP(16*9-128,"ebx"),"xmm1"); + &movdqa (&QWP(16*10-128,"ebx"),"xmm2"); + &movdqa (&QWP(16*11-128,"ebx"),"xmm3"); + &movdqa (&QWP(16*12-128,"ebx"),"xmm4"); + &movdqa (&QWP(16*13-128,"ebx"),"xmm5"); + &movdqa (&QWP(16*14-128,"ebx"),"xmm6"); + &movdqa (&QWP(16*15-128,"ebx"),"xmm7"); + &movdqa (&QWP(16*12-128,"ebp"),"xmm4"); # save counter value + + &movdqa ($xa, &QWP(16*0-128,"ebp")); + &movdqa ($xd, "xmm4"); + &movdqa ($xb_,&QWP(16*4-128,"ebp")); + &movdqa ($xc, &QWP(16*8-128,"ebp")); + &movdqa ($xc_,&QWP(16*9-128,"ebp")); + + &mov ("edx",10); # loop counter + &nop (); + +&set_label("loop",16); + &paddd ($xa,$xb_); # elsewhere + &movdqa ($xb,$xb_); + &pxor ($xd,$xa); # elsewhere + &QUARTERROUND_SSSE3(0, 4, 8, 12, 0); + &QUARTERROUND_SSSE3(1, 5, 9, 13, 1); + &QUARTERROUND_SSSE3(2, 6,10, 14, 2); + &QUARTERROUND_SSSE3(3, 7,11, 15, 3); + &QUARTERROUND_SSSE3(0, 5,10, 15, 4); + &QUARTERROUND_SSSE3(1, 6,11, 12, 5); + &QUARTERROUND_SSSE3(2, 7, 8, 13, 6); + &QUARTERROUND_SSSE3(3, 4, 9, 14, 7); + &dec ("edx"); + &jnz (&label("loop")); + + &movdqa (&QWP(16*4-128,"ebx"),$xb_); + &movdqa (&QWP(16*8-128,"ebx"),$xc); + &movdqa (&QWP(16*9-128,"ebx"),$xc_); + &movdqa (&QWP(16*12-128,"ebx"),$xd); + &movdqa (&QWP(16*14-128,"ebx"),$xd_); + + my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7)); + + #&movdqa ($xa0,&QWP(16*0-128,"ebx")); # it's there + &movdqa ($xa1,&QWP(16*1-128,"ebx")); + &movdqa ($xa2,&QWP(16*2-128,"ebx")); + &movdqa ($xa3,&QWP(16*3-128,"ebx")); + + for($i=0;$i<256;$i+=64) { + &paddd ($xa0,&QWP($i+16*0-128,"ebp")); # accumulate key material + &paddd ($xa1,&QWP($i+16*1-128,"ebp")); + &paddd ($xa2,&QWP($i+16*2-128,"ebp")); + &paddd ($xa3,&QWP($i+16*3-128,"ebp")); + + &movdqa ($xt2,$xa0); # "de-interlace" data + &punpckldq ($xa0,$xa1); + &movdqa ($xt3,$xa2); + &punpckldq ($xa2,$xa3); + &punpckhdq ($xt2,$xa1); + &punpckhdq ($xt3,$xa3); + &movdqa ($xa1,$xa0); + &punpcklqdq ($xa0,$xa2); # "a0" + &movdqa ($xa3,$xt2); + &punpcklqdq ($xt2,$xt3); # "a2" + &punpckhqdq ($xa1,$xa2); # "a1" + &punpckhqdq ($xa3,$xt3); # "a3" + + #($xa2,$xt2)=($xt2,$xa2); + + &movdqu ($xt0,&QWP(64*0-128,$inp)); # load input + &movdqu ($xt1,&QWP(64*1-128,$inp)); + &movdqu ($xa2,&QWP(64*2-128,$inp)); + &movdqu ($xt3,&QWP(64*3-128,$inp)); + &lea ($inp,&QWP($i<192?16:(64*4-16*3),$inp)); + &pxor ($xt0,$xa0); + &movdqa ($xa0,&QWP($i+16*4-128,"ebx")) if ($i<192); + &pxor ($xt1,$xa1); + &movdqa ($xa1,&QWP($i+16*5-128,"ebx")) if ($i<192); + &pxor ($xt2,$xa2); + &movdqa ($xa2,&QWP($i+16*6-128,"ebx")) if ($i<192); + &pxor ($xt3,$xa3); + &movdqa ($xa3,&QWP($i+16*7-128,"ebx")) if ($i<192); + &movdqu (&QWP(64*0-128,$out),$xt0); # store output + &movdqu (&QWP(64*1-128,$out),$xt1); + &movdqu (&QWP(64*2-128,$out),$xt2); + &movdqu (&QWP(64*3-128,$out),$xt3); + &lea ($out,&QWP($i<192?16:(64*4-16*3),$out)); + } + &sub ($len,64*4); + &jnc (&label("outer_loop")); + + &add ($len,64*4); + &jz (&label("done")); + + &mov ("ebx",&DWP(512+8,"esp")); # restore pointers + &lea ($inp,&DWP(-128,$inp)); + &mov ("edx",&DWP(512+4,"esp")); + &lea ($out,&DWP(-128,$out)); + + &movd ("xmm2",&DWP(16*12-128,"ebp")); # counter value + &movdqu ("xmm3",&QWP(0,"ebx")); + &paddd ("xmm2",&QWP(16*6,"eax")); # +four + &pand ("xmm3",&QWP(16*7,"eax")); + &por ("xmm3","xmm2"); # counter value +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7)); + +sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot16); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,20); + &pslld ($t,12); + &por ($b,$t); + + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot24); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,25); + &pslld ($t,7); + &por ($b,$t); +} + +&set_label("1x"); + &movdqa ($a,&QWP(16*2,"eax")); # sigma + &movdqu ($b,&QWP(0,"edx")); + &movdqu ($c,&QWP(16,"edx")); + #&movdqu ($d,&QWP(0,"ebx")); # already loaded + &movdqa ($rot16,&QWP(0,"eax")); + &movdqa ($rot24,&QWP(16,"eax")); + &mov (&DWP(16*3,"esp"),"ebp"); + + &movdqa (&QWP(16*0,"esp"),$a); + &movdqa (&QWP(16*1,"esp"),$b); + &movdqa (&QWP(16*2,"esp"),$c); + &movdqa (&QWP(16*3,"esp"),$d); + &mov ("edx",10); + &jmp (&label("loop1x")); + +&set_label("outer1x",16); + &movdqa ($d,&QWP(16*5,"eax")); # one + &movdqa ($a,&QWP(16*0,"esp")); + &movdqa ($b,&QWP(16*1,"esp")); + &movdqa ($c,&QWP(16*2,"esp")); + &paddd ($d,&QWP(16*3,"esp")); + &mov ("edx",10); + &movdqa (&QWP(16*3,"esp"),$d); + &jmp (&label("loop1x")); + +&set_label("loop1x",16); + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b00111001); + &pshufd ($d,$d,0b10010011); + &nop (); + + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b10010011); + &pshufd ($d,$d,0b00111001); + + &dec ("edx"); + &jnz (&label("loop1x")); + + &paddd ($a,&QWP(16*0,"esp")); + &paddd ($b,&QWP(16*1,"esp")); + &paddd ($c,&QWP(16*2,"esp")); + &paddd ($d,&QWP(16*3,"esp")); + + &cmp ($len,64); + &jb (&label("tail")); + + &movdqu ($t,&QWP(16*0,$inp)); + &movdqu ($t1,&QWP(16*1,$inp)); + &pxor ($a,$t); # xor with input + &movdqu ($t,&QWP(16*2,$inp)); + &pxor ($b,$t1); + &movdqu ($t1,&QWP(16*3,$inp)); + &pxor ($c,$t); + &pxor ($d,$t1); + &lea ($inp,&DWP(16*4,$inp)); # inp+=64 + + &movdqu (&QWP(16*0,$out),$a); # write output + &movdqu (&QWP(16*1,$out),$b); + &movdqu (&QWP(16*2,$out),$c); + &movdqu (&QWP(16*3,$out),$d); + &lea ($out,&DWP(16*4,$out)); # inp+=64 + + &sub ($len,64); + &jnz (&label("outer1x")); + + &jmp (&label("done")); + +&set_label("tail"); + &movdqa (&QWP(16*0,"esp"),$a); + &movdqa (&QWP(16*1,"esp"),$b); + &movdqa (&QWP(16*2,"esp"),$c); + &movdqa (&QWP(16*3,"esp"),$d); + + &xor ("eax","eax"); + &xor ("edx","edx"); + &xor ("ebp","ebp"); + +&set_label("tail_loop"); + &movb ("al",&BP(0,"esp","ebp")); + &movb ("dl",&BP(0,$inp,"ebp")); + &lea ("ebp",&DWP(1,"ebp")); + &xor ("al","dl"); + &movb (&BP(-1,$out,"ebp"),"al"); + &dec ($len); + &jnz (&label("tail_loop")); +} +&set_label("done"); + &mov ("esp",&DWP(512,"esp")); +&function_end("ChaCha20_ssse3"); + +&align (64); +&set_label("ssse3_data"); +&data_byte(0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd); +&data_byte(0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe); +&data_word(0x61707865,0x3320646e,0x79622d32,0x6b206574); +&data_word(0,1,2,3); +&data_word(4,4,4,4); +&data_word(1,0,0,0); +&data_word(4,0,0,0); +&data_word(0,-1,-1,-1); +&align (64); +} +&asciz ("ChaCha20 for x86, CRYPTOGAMS by "); + +&asm_finish(); diff --git a/external/boringssl/crypto/chacha/asm/chacha-x86_64.pl b/external/boringssl/crypto/chacha/asm/chacha-x86_64.pl new file mode 100755 index 0000000000..55b726d230 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-x86_64.pl @@ -0,0 +1,1767 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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/. +# ==================================================================== +# +# November 2014 +# +# ChaCha20 for x86_64. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc 4.8(i) 1xSSSE3/SSE2 4xSSSE3 8xAVX2 +# +# P4 9.48/+99% -/22.7(ii) - +# Core2 7.83/+55% 7.90/8.08 4.35 +# Westmere 7.19/+50% 5.60/6.70 3.00 +# Sandy Bridge 8.31/+42% 5.45/6.76 2.72 +# Ivy Bridge 6.71/+46% 5.40/6.49 2.41 +# Haswell 5.92/+43% 5.20/6.45 2.42 1.23 +# Silvermont 12.0/+33% 7.75/7.40 7.03(iii) +# Sledgehammer 7.28/+52% -/14.2(ii) - +# Bulldozer 9.66/+28% 9.85/11.1 3.06(iv) +# VIA Nano 10.5/+46% 6.72/8.60 6.05 +# +# (i) compared to older gcc 3.x one can observe >2x improvement on +# most platforms; +# (ii) as it can be seen, SSE2 performance is too low on legacy +# processors; NxSSE2 results are naturally better, but not +# impressively better than IALU ones, which is why you won't +# find SSE2 code below; +# (iii) this is not optimal result for Atom because of MSROM +# limitations, SSE2 can do better, but gain is considered too +# low to justify the [maintenance] effort; +# (iv) Bulldozer actually executes 4xXOP code path that delivers 2.20; +# +# Modified from upstream OpenSSL to remove the XOP code. + +$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"; + +$avx = 2; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +# input parameter block +($out,$inp,$len,$key,$counter)=("%rdi","%rsi","%rdx","%rcx","%r8"); + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.align 64 +.Lzero: +.long 0,0,0,0 +.Lone: +.long 1,0,0,0 +.Linc: +.long 0,1,2,3 +.Lfour: +.long 4,4,4,4 +.Lincy: +.long 0,2,4,6,1,3,5,7 +.Leight: +.long 8,8,8,8,8,8,8,8 +.Lrot16: +.byte 0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd +.Lrot24: +.byte 0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe +.Lsigma: +.asciz "expand 32-byte k" +.asciz "ChaCha20 for x86_64, CRYPTOGAMS by " +___ + +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"; +} + +@x=("%eax","%ebx","%ecx","%edx",map("%r${_}d",(8..11)), + "%nox","%nox","%nox","%nox",map("%r${_}d",(12..15))); +@t=("%esi","%edi"); + +sub ROUND { # critical path is 24 cycles per round +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_)=map("\"$_\"",@t); +my @x=map("\"$_\"",@x); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + # Normally instructions would be interleaved to favour in-order + # execution. Generally out-of-order cores manage it gracefully, + # but not this time for some reason. As in-order execution + # cores are dying breed, old Atom is the only one around, + # instructions are left uninterleaved. Besides, Atom is better + # off executing 1xSSSE3 code anyway... + + ( + "&add (@x[$a0],@x[$b0])", # Q1 + "&xor (@x[$d0],@x[$a0])", + "&rol (@x[$d0],16)", + "&add (@x[$a1],@x[$b1])", # Q2 + "&xor (@x[$d1],@x[$a1])", + "&rol (@x[$d1],16)", + + "&add ($xc,@x[$d0])", + "&xor (@x[$b0],$xc)", + "&rol (@x[$b0],12)", + "&add ($xc_,@x[$d1])", + "&xor (@x[$b1],$xc_)", + "&rol (@x[$b1],12)", + + "&add (@x[$a0],@x[$b0])", + "&xor (@x[$d0],@x[$a0])", + "&rol (@x[$d0],8)", + "&add (@x[$a1],@x[$b1])", + "&xor (@x[$d1],@x[$a1])", + "&rol (@x[$d1],8)", + + "&add ($xc,@x[$d0])", + "&xor (@x[$b0],$xc)", + "&rol (@x[$b0],7)", + "&add ($xc_,@x[$d1])", + "&xor (@x[$b1],$xc_)", + "&rol (@x[$b1],7)", + + "&mov (\"4*$c0(%rsp)\",$xc)", # reload pair of 'c's + "&mov (\"4*$c1(%rsp)\",$xc_)", + "&mov ($xc,\"4*$c2(%rsp)\")", + "&mov ($xc_,\"4*$c3(%rsp)\")", + + "&add (@x[$a2],@x[$b2])", # Q3 + "&xor (@x[$d2],@x[$a2])", + "&rol (@x[$d2],16)", + "&add (@x[$a3],@x[$b3])", # Q4 + "&xor (@x[$d3],@x[$a3])", + "&rol (@x[$d3],16)", + + "&add ($xc,@x[$d2])", + "&xor (@x[$b2],$xc)", + "&rol (@x[$b2],12)", + "&add ($xc_,@x[$d3])", + "&xor (@x[$b3],$xc_)", + "&rol (@x[$b3],12)", + + "&add (@x[$a2],@x[$b2])", + "&xor (@x[$d2],@x[$a2])", + "&rol (@x[$d2],8)", + "&add (@x[$a3],@x[$b3])", + "&xor (@x[$d3],@x[$a3])", + "&rol (@x[$d3],8)", + + "&add ($xc,@x[$d2])", + "&xor (@x[$b2],$xc)", + "&rol (@x[$b2],7)", + "&add ($xc_,@x[$d3])", + "&xor (@x[$b3],$xc_)", + "&rol (@x[$b3],7)" + ); +} + +######################################################################## +# Generic code path that handles all lengths on pre-SSSE3 processors. +$code.=<<___; +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,\@function,5 +.align 64 +ChaCha20_ctr32: + cmp \$0,$len + je .Lno_data + mov OPENSSL_ia32cap_P+4(%rip),%r10 + test \$`1<<(41-32)`,%r10d + jnz .LChaCha20_ssse3 + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + sub \$64+24,%rsp + + #movdqa .Lsigma(%rip),%xmm0 + movdqu ($key),%xmm1 + movdqu 16($key),%xmm2 + movdqu ($counter),%xmm3 + movdqa .Lone(%rip),%xmm4 + + #movdqa %xmm0,4*0(%rsp) # key[0] + movdqa %xmm1,4*4(%rsp) # key[1] + movdqa %xmm2,4*8(%rsp) # key[2] + movdqa %xmm3,4*12(%rsp) # key[3] + mov $len,%rbp # reassign $len + jmp .Loop_outer + +.align 32 +.Loop_outer: + mov \$0x61707865,@x[0] # 'expa' + mov \$0x3320646e,@x[1] # 'nd 3' + mov \$0x79622d32,@x[2] # '2-by' + mov \$0x6b206574,@x[3] # 'te k' + mov 4*4(%rsp),@x[4] + mov 4*5(%rsp),@x[5] + mov 4*6(%rsp),@x[6] + mov 4*7(%rsp),@x[7] + movd %xmm3,@x[12] + mov 4*13(%rsp),@x[13] + mov 4*14(%rsp),@x[14] + mov 4*15(%rsp),@x[15] + + mov %rbp,64+0(%rsp) # save len + mov \$10,%ebp + mov $inp,64+8(%rsp) # save inp + movq %xmm2,%rsi # "@x[8]" + mov $out,64+16(%rsp) # save out + mov %rsi,%rdi + shr \$32,%rdi # "@x[9]" + jmp .Loop + +.align 32 +.Loop: +___ + foreach (&ROUND (0, 4, 8,12)) { eval; } + foreach (&ROUND (0, 5,10,15)) { eval; } + &dec ("%ebp"); + &jnz (".Loop"); + +$code.=<<___; + mov @t[1],4*9(%rsp) # modulo-scheduled + mov @t[0],4*8(%rsp) + mov 64(%rsp),%rbp # load len + movdqa %xmm2,%xmm1 + mov 64+8(%rsp),$inp # load inp + paddd %xmm4,%xmm3 # increment counter + mov 64+16(%rsp),$out # load out + + add \$0x61707865,@x[0] # 'expa' + add \$0x3320646e,@x[1] # 'nd 3' + add \$0x79622d32,@x[2] # '2-by' + add \$0x6b206574,@x[3] # 'te k' + add 4*4(%rsp),@x[4] + add 4*5(%rsp),@x[5] + add 4*6(%rsp),@x[6] + add 4*7(%rsp),@x[7] + add 4*12(%rsp),@x[12] + add 4*13(%rsp),@x[13] + add 4*14(%rsp),@x[14] + add 4*15(%rsp),@x[15] + paddd 4*8(%rsp),%xmm1 + + cmp \$64,%rbp + jb .Ltail + + xor 4*0($inp),@x[0] # xor with input + xor 4*1($inp),@x[1] + xor 4*2($inp),@x[2] + xor 4*3($inp),@x[3] + xor 4*4($inp),@x[4] + xor 4*5($inp),@x[5] + xor 4*6($inp),@x[6] + xor 4*7($inp),@x[7] + movdqu 4*8($inp),%xmm0 + xor 4*12($inp),@x[12] + xor 4*13($inp),@x[13] + xor 4*14($inp),@x[14] + xor 4*15($inp),@x[15] + lea 4*16($inp),$inp # inp+=64 + pxor %xmm1,%xmm0 + + movdqa %xmm2,4*8(%rsp) + movd %xmm3,4*12(%rsp) + + mov @x[0],4*0($out) # write output + mov @x[1],4*1($out) + mov @x[2],4*2($out) + mov @x[3],4*3($out) + mov @x[4],4*4($out) + mov @x[5],4*5($out) + mov @x[6],4*6($out) + mov @x[7],4*7($out) + movdqu %xmm0,4*8($out) + mov @x[12],4*12($out) + mov @x[13],4*13($out) + mov @x[14],4*14($out) + mov @x[15],4*15($out) + lea 4*16($out),$out # out+=64 + + sub \$64,%rbp + jnz .Loop_outer + + jmp .Ldone + +.align 16 +.Ltail: + mov @x[0],4*0(%rsp) + mov @x[1],4*1(%rsp) + xor %rbx,%rbx + mov @x[2],4*2(%rsp) + mov @x[3],4*3(%rsp) + mov @x[4],4*4(%rsp) + mov @x[5],4*5(%rsp) + mov @x[6],4*6(%rsp) + mov @x[7],4*7(%rsp) + movdqa %xmm1,4*8(%rsp) + mov @x[12],4*12(%rsp) + mov @x[13],4*13(%rsp) + mov @x[14],4*14(%rsp) + mov @x[15],4*15(%rsp) + +.Loop_tail: + movzb ($inp,%rbx),%eax + movzb (%rsp,%rbx),%edx + lea 1(%rbx),%rbx + xor %edx,%eax + mov %al,-1($out,%rbx) + dec %rbp + jnz .Loop_tail + +.Ldone: + add \$64+24,%rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx +.Lno_data: + ret +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +######################################################################## +# SSSE3 code path that handles shorter lengths +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("%xmm$_",(0..7)); + +sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot16); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,20); + &pslld ($t,12); + &por ($b,$t); + + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot24); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,25); + &pslld ($t,7); + &por ($b,$t); +} + +my $xframe = $win64 ? 32+32+8 : 24; + +$code.=<<___; +.type ChaCha20_ssse3,\@function,5 +.align 32 +ChaCha20_ssse3: +.LChaCha20_ssse3: +___ +$code.=<<___; + cmp \$128,$len # we might throw away some data, + ja .LChaCha20_4x # but overall it won't be slower + +.Ldo_sse3_after_all: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + sub \$64+$xframe,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,64+32(%rsp) + movaps %xmm7,64+48(%rsp) +___ +$code.=<<___; + movdqa .Lsigma(%rip),$a + movdqu ($key),$b + movdqu 16($key),$c + movdqu ($counter),$d + movdqa .Lrot16(%rip),$rot16 + movdqa .Lrot24(%rip),$rot24 + + movdqa $a,0x00(%rsp) + movdqa $b,0x10(%rsp) + movdqa $c,0x20(%rsp) + movdqa $d,0x30(%rsp) + mov \$10,%ebp + jmp .Loop_ssse3 + +.align 32 +.Loop_outer_ssse3: + movdqa .Lone(%rip),$d + movdqa 0x00(%rsp),$a + movdqa 0x10(%rsp),$b + movdqa 0x20(%rsp),$c + paddd 0x30(%rsp),$d + mov \$10,%ebp + movdqa $d,0x30(%rsp) + jmp .Loop_ssse3 + +.align 32 +.Loop_ssse3: +___ + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b00111001); + &pshufd ($d,$d,0b10010011); + &nop (); + + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b10010011); + &pshufd ($d,$d,0b00111001); + + &dec ("%ebp"); + &jnz (".Loop_ssse3"); + +$code.=<<___; + paddd 0x00(%rsp),$a + paddd 0x10(%rsp),$b + paddd 0x20(%rsp),$c + paddd 0x30(%rsp),$d + + cmp \$64,$len + jb .Ltail_ssse3 + + movdqu 0x00($inp),$t + movdqu 0x10($inp),$t1 + pxor $t,$a # xor with input + movdqu 0x20($inp),$t + pxor $t1,$b + movdqu 0x30($inp),$t1 + lea 0x40($inp),$inp # inp+=64 + pxor $t,$c + pxor $t1,$d + + movdqu $a,0x00($out) # write output + movdqu $b,0x10($out) + movdqu $c,0x20($out) + movdqu $d,0x30($out) + lea 0x40($out),$out # out+=64 + + sub \$64,$len + jnz .Loop_outer_ssse3 + + jmp .Ldone_ssse3 + +.align 16 +.Ltail_ssse3: + movdqa $a,0x00(%rsp) + movdqa $b,0x10(%rsp) + movdqa $c,0x20(%rsp) + movdqa $d,0x30(%rsp) + xor %rbx,%rbx + +.Loop_tail_ssse3: + movzb ($inp,%rbx),%eax + movzb (%rsp,%rbx),%ecx + lea 1(%rbx),%rbx + xor %ecx,%eax + mov %al,-1($out,%rbx) + dec $len + jnz .Loop_tail_ssse3 + +.Ldone_ssse3: +___ +$code.=<<___ if ($win64); + movaps 64+32(%rsp),%xmm6 + movaps 64+48(%rsp),%xmm7 +___ +$code.=<<___; + add \$64+$xframe,%rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret +.size ChaCha20_ssse3,.-ChaCha20_ssse3 +___ +} + +######################################################################## +# SSSE3 code path that handles longer messages. +{ +# assign variables to favor Atom front-end +my ($xd0,$xd1,$xd2,$xd3, $xt0,$xt1,$xt2,$xt3, + $xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3)=map("%xmm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3); + +sub SSSE3_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3); +my @x=map("\"$_\"",@xx); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + ( + "&paddd (@x[$a0],@x[$b0])", # Q1 + "&paddd (@x[$a1],@x[$b1])", # Q2 + "&pxor (@x[$d0],@x[$a0])", + "&pxor (@x[$d1],@x[$a1])", + "&pshufb (@x[$d0],$t1)", + "&pshufb (@x[$d1],$t1)", + + "&paddd ($xc,@x[$d0])", + "&paddd ($xc_,@x[$d1])", + "&pxor (@x[$b0],$xc)", + "&pxor (@x[$b1],$xc_)", + "&movdqa ($t0,@x[$b0])", + "&pslld (@x[$b0],12)", + "&psrld ($t0,20)", + "&movdqa ($t1,@x[$b1])", + "&pslld (@x[$b1],12)", + "&por (@x[$b0],$t0)", + "&psrld ($t1,20)", + "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip) + "&por (@x[$b1],$t1)", + + "&paddd (@x[$a0],@x[$b0])", + "&paddd (@x[$a1],@x[$b1])", + "&pxor (@x[$d0],@x[$a0])", + "&pxor (@x[$d1],@x[$a1])", + "&pshufb (@x[$d0],$t0)", + "&pshufb (@x[$d1],$t0)", + + "&paddd ($xc,@x[$d0])", + "&paddd ($xc_,@x[$d1])", + "&pxor (@x[$b0],$xc)", + "&pxor (@x[$b1],$xc_)", + "&movdqa ($t1,@x[$b0])", + "&pslld (@x[$b0],7)", + "&psrld ($t1,25)", + "&movdqa ($t0,@x[$b1])", + "&pslld (@x[$b1],7)", + "&por (@x[$b0],$t1)", + "&psrld ($t0,25)", + "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip) + "&por (@x[$b1],$t0)", + + "&movdqa (\"`16*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's + "&movdqa (\"`16*($c1-8)`(%rsp)\",$xc_)", + "&movdqa ($xc,\"`16*($c2-8)`(%rsp)\")", + "&movdqa ($xc_,\"`16*($c3-8)`(%rsp)\")", + + "&paddd (@x[$a2],@x[$b2])", # Q3 + "&paddd (@x[$a3],@x[$b3])", # Q4 + "&pxor (@x[$d2],@x[$a2])", + "&pxor (@x[$d3],@x[$a3])", + "&pshufb (@x[$d2],$t1)", + "&pshufb (@x[$d3],$t1)", + + "&paddd ($xc,@x[$d2])", + "&paddd ($xc_,@x[$d3])", + "&pxor (@x[$b2],$xc)", + "&pxor (@x[$b3],$xc_)", + "&movdqa ($t0,@x[$b2])", + "&pslld (@x[$b2],12)", + "&psrld ($t0,20)", + "&movdqa ($t1,@x[$b3])", + "&pslld (@x[$b3],12)", + "&por (@x[$b2],$t0)", + "&psrld ($t1,20)", + "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip) + "&por (@x[$b3],$t1)", + + "&paddd (@x[$a2],@x[$b2])", + "&paddd (@x[$a3],@x[$b3])", + "&pxor (@x[$d2],@x[$a2])", + "&pxor (@x[$d3],@x[$a3])", + "&pshufb (@x[$d2],$t0)", + "&pshufb (@x[$d3],$t0)", + + "&paddd ($xc,@x[$d2])", + "&paddd ($xc_,@x[$d3])", + "&pxor (@x[$b2],$xc)", + "&pxor (@x[$b3],$xc_)", + "&movdqa ($t1,@x[$b2])", + "&pslld (@x[$b2],7)", + "&psrld ($t1,25)", + "&movdqa ($t0,@x[$b3])", + "&pslld (@x[$b3],7)", + "&por (@x[$b2],$t1)", + "&psrld ($t0,25)", + "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip) + "&por (@x[$b3],$t0)" + ); +} + +my $xframe = $win64 ? 0xa0 : 0; + +$code.=<<___; +.type ChaCha20_4x,\@function,5 +.align 32 +ChaCha20_4x: +.LChaCha20_4x: + mov %r10,%r11 +___ +$code.=<<___ if ($avx>1); + shr \$32,%r10 # OPENSSL_ia32cap_P+8 + test \$`1<<5`,%r10 # test AVX2 + jnz .LChaCha20_8x +___ +$code.=<<___; + cmp \$192,$len + ja .Lproceed4x + + and \$`1<<26|1<<22`,%r11 # isolate XSAVE+MOVBE + cmp \$`1<<22`,%r11 # check for MOVBE without XSAVE + je .Ldo_sse3_after_all # to detect Atom + +.Lproceed4x: + lea -0x78(%rsp),%r11 + sub \$0x148+$xframe,%rsp +___ + ################ stack layout + # +0x00 SIMD equivalent of @x[8-12] + # ... + # +0x40 constant copy of key[0-2] smashed by lanes + # ... + # +0x100 SIMD counters (with nonce smashed by lanes) + # ... + # +0x140 +$code.=<<___ if ($win64); + movaps %xmm6,-0x30(%r11) + movaps %xmm7,-0x20(%r11) + movaps %xmm8,-0x10(%r11) + movaps %xmm9,0x00(%r11) + movaps %xmm10,0x10(%r11) + movaps %xmm11,0x20(%r11) + movaps %xmm12,0x30(%r11) + movaps %xmm13,0x40(%r11) + movaps %xmm14,0x50(%r11) + movaps %xmm15,0x60(%r11) +___ +$code.=<<___; + movdqa .Lsigma(%rip),$xa3 # key[0] + movdqu ($key),$xb3 # key[1] + movdqu 16($key),$xt3 # key[2] + movdqu ($counter),$xd3 # key[3] + lea 0x100(%rsp),%rcx # size optimization + lea .Lrot16(%rip),%r10 + lea .Lrot24(%rip),%r11 + + pshufd \$0x00,$xa3,$xa0 # smash key by lanes... + pshufd \$0x55,$xa3,$xa1 + movdqa $xa0,0x40(%rsp) # ... and offload + pshufd \$0xaa,$xa3,$xa2 + movdqa $xa1,0x50(%rsp) + pshufd \$0xff,$xa3,$xa3 + movdqa $xa2,0x60(%rsp) + movdqa $xa3,0x70(%rsp) + + pshufd \$0x00,$xb3,$xb0 + pshufd \$0x55,$xb3,$xb1 + movdqa $xb0,0x80-0x100(%rcx) + pshufd \$0xaa,$xb3,$xb2 + movdqa $xb1,0x90-0x100(%rcx) + pshufd \$0xff,$xb3,$xb3 + movdqa $xb2,0xa0-0x100(%rcx) + movdqa $xb3,0xb0-0x100(%rcx) + + pshufd \$0x00,$xt3,$xt0 # "$xc0" + pshufd \$0x55,$xt3,$xt1 # "$xc1" + movdqa $xt0,0xc0-0x100(%rcx) + pshufd \$0xaa,$xt3,$xt2 # "$xc2" + movdqa $xt1,0xd0-0x100(%rcx) + pshufd \$0xff,$xt3,$xt3 # "$xc3" + movdqa $xt2,0xe0-0x100(%rcx) + movdqa $xt3,0xf0-0x100(%rcx) + + pshufd \$0x00,$xd3,$xd0 + pshufd \$0x55,$xd3,$xd1 + paddd .Linc(%rip),$xd0 # don't save counters yet + pshufd \$0xaa,$xd3,$xd2 + movdqa $xd1,0x110-0x100(%rcx) + pshufd \$0xff,$xd3,$xd3 + movdqa $xd2,0x120-0x100(%rcx) + movdqa $xd3,0x130-0x100(%rcx) + + jmp .Loop_enter4x + +.align 32 +.Loop_outer4x: + movdqa 0x40(%rsp),$xa0 # re-load smashed key + movdqa 0x50(%rsp),$xa1 + movdqa 0x60(%rsp),$xa2 + movdqa 0x70(%rsp),$xa3 + movdqa 0x80-0x100(%rcx),$xb0 + movdqa 0x90-0x100(%rcx),$xb1 + movdqa 0xa0-0x100(%rcx),$xb2 + movdqa 0xb0-0x100(%rcx),$xb3 + movdqa 0xc0-0x100(%rcx),$xt0 # "$xc0" + movdqa 0xd0-0x100(%rcx),$xt1 # "$xc1" + movdqa 0xe0-0x100(%rcx),$xt2 # "$xc2" + movdqa 0xf0-0x100(%rcx),$xt3 # "$xc3" + movdqa 0x100-0x100(%rcx),$xd0 + movdqa 0x110-0x100(%rcx),$xd1 + movdqa 0x120-0x100(%rcx),$xd2 + movdqa 0x130-0x100(%rcx),$xd3 + paddd .Lfour(%rip),$xd0 # next SIMD counters + +.Loop_enter4x: + movdqa $xt2,0x20(%rsp) # SIMD equivalent of "@x[10]" + movdqa $xt3,0x30(%rsp) # SIMD equivalent of "@x[11]" + movdqa (%r10),$xt3 # .Lrot16(%rip) + mov \$10,%eax + movdqa $xd0,0x100-0x100(%rcx) # save SIMD counters + jmp .Loop4x + +.align 32 +.Loop4x: +___ + foreach (&SSSE3_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&SSSE3_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop4x + + paddd 0x40(%rsp),$xa0 # accumulate key material + paddd 0x50(%rsp),$xa1 + paddd 0x60(%rsp),$xa2 + paddd 0x70(%rsp),$xa3 + + movdqa $xa0,$xt2 # "de-interlace" data + punpckldq $xa1,$xa0 + movdqa $xa2,$xt3 + punpckldq $xa3,$xa2 + punpckhdq $xa1,$xt2 + punpckhdq $xa3,$xt3 + movdqa $xa0,$xa1 + punpcklqdq $xa2,$xa0 # "a0" + movdqa $xt2,$xa3 + punpcklqdq $xt3,$xt2 # "a2" + punpckhqdq $xa2,$xa1 # "a1" + punpckhqdq $xt3,$xa3 # "a3" +___ + ($xa2,$xt2)=($xt2,$xa2); +$code.=<<___; + paddd 0x80-0x100(%rcx),$xb0 + paddd 0x90-0x100(%rcx),$xb1 + paddd 0xa0-0x100(%rcx),$xb2 + paddd 0xb0-0x100(%rcx),$xb3 + + movdqa $xa0,0x00(%rsp) # offload $xaN + movdqa $xa1,0x10(%rsp) + movdqa 0x20(%rsp),$xa0 # "xc2" + movdqa 0x30(%rsp),$xa1 # "xc3" + + movdqa $xb0,$xt2 + punpckldq $xb1,$xb0 + movdqa $xb2,$xt3 + punpckldq $xb3,$xb2 + punpckhdq $xb1,$xt2 + punpckhdq $xb3,$xt3 + movdqa $xb0,$xb1 + punpcklqdq $xb2,$xb0 # "b0" + movdqa $xt2,$xb3 + punpcklqdq $xt3,$xt2 # "b2" + punpckhqdq $xb2,$xb1 # "b1" + punpckhqdq $xt3,$xb3 # "b3" +___ + ($xb2,$xt2)=($xt2,$xb2); + my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1); +$code.=<<___; + paddd 0xc0-0x100(%rcx),$xc0 + paddd 0xd0-0x100(%rcx),$xc1 + paddd 0xe0-0x100(%rcx),$xc2 + paddd 0xf0-0x100(%rcx),$xc3 + + movdqa $xa2,0x20(%rsp) # keep offloading $xaN + movdqa $xa3,0x30(%rsp) + + movdqa $xc0,$xt2 + punpckldq $xc1,$xc0 + movdqa $xc2,$xt3 + punpckldq $xc3,$xc2 + punpckhdq $xc1,$xt2 + punpckhdq $xc3,$xt3 + movdqa $xc0,$xc1 + punpcklqdq $xc2,$xc0 # "c0" + movdqa $xt2,$xc3 + punpcklqdq $xt3,$xt2 # "c2" + punpckhqdq $xc2,$xc1 # "c1" + punpckhqdq $xt3,$xc3 # "c3" +___ + ($xc2,$xt2)=($xt2,$xc2); + ($xt0,$xt1)=($xa2,$xa3); # use $xaN as temporary +$code.=<<___; + paddd 0x100-0x100(%rcx),$xd0 + paddd 0x110-0x100(%rcx),$xd1 + paddd 0x120-0x100(%rcx),$xd2 + paddd 0x130-0x100(%rcx),$xd3 + + movdqa $xd0,$xt2 + punpckldq $xd1,$xd0 + movdqa $xd2,$xt3 + punpckldq $xd3,$xd2 + punpckhdq $xd1,$xt2 + punpckhdq $xd3,$xt3 + movdqa $xd0,$xd1 + punpcklqdq $xd2,$xd0 # "d0" + movdqa $xt2,$xd3 + punpcklqdq $xt3,$xt2 # "d2" + punpckhqdq $xd2,$xd1 # "d1" + punpckhqdq $xt3,$xd3 # "d3" +___ + ($xd2,$xt2)=($xt2,$xd2); +$code.=<<___; + cmp \$64*4,$len + jb .Ltail4x + + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # size optimization + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + + movdqu $xt0,0x40($out) + movdqu 0x00($inp),$xt0 + movdqu $xt1,0x50($out) + movdqu 0x10($inp),$xt1 + movdqu $xt2,0x60($out) + movdqu 0x20($inp),$xt2 + movdqu $xt3,0x70($out) + lea 0x80($out),$out # size optimization + movdqu 0x30($inp),$xt3 + pxor 0x20(%rsp),$xt0 + pxor $xb2,$xt1 + pxor $xc2,$xt2 + pxor $xd2,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # inp+=64*4 + pxor 0x30(%rsp),$xt0 + pxor $xb3,$xt1 + pxor $xc3,$xt2 + pxor $xd3,$xt3 + movdqu $xt0,0x40($out) + movdqu $xt1,0x50($out) + movdqu $xt2,0x60($out) + movdqu $xt3,0x70($out) + lea 0x80($out),$out # out+=64*4 + + sub \$64*4,$len + jnz .Loop_outer4x + + jmp .Ldone4x + +.Ltail4x: + cmp \$192,$len + jae .L192_or_more4x + cmp \$128,$len + jae .L128_or_more4x + cmp \$64,$len + jae .L64_or_more4x + + #movdqa 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + xor %r10,%r10 + #movdqa $xt0,0x00(%rsp) + movdqa $xb0,0x10(%rsp) + movdqa $xc0,0x20(%rsp) + movdqa $xd0,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L64_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaxN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + movdqu $xt0,0x00($out) + movdqu $xt1,0x10($out) + movdqu $xt2,0x20($out) + movdqu $xt3,0x30($out) + je .Ldone4x + + movdqa 0x10(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x40($inp),$inp # inp+=64*1 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb1,0x10(%rsp) + lea 0x40($out),$out # out+=64*1 + movdqa $xc1,0x20(%rsp) + sub \$64,$len # len-=64*1 + movdqa $xd1,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L128_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + movdqu $xt0,0x40($out) + movdqu $xt1,0x50($out) + movdqu $xt2,0x60($out) + movdqu $xt3,0x70($out) + je .Ldone4x + + movdqa 0x20(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x80($inp),$inp # inp+=64*2 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb2,0x10(%rsp) + lea 0x80($out),$out # out+=64*2 + movdqa $xc2,0x20(%rsp) + sub \$128,$len # len-=64*2 + movdqa $xd2,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L192_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # size optimization + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + + movdqu $xt0,0x40($out) + movdqu 0x00($inp),$xt0 + movdqu $xt1,0x50($out) + movdqu 0x10($inp),$xt1 + movdqu $xt2,0x60($out) + movdqu 0x20($inp),$xt2 + movdqu $xt3,0x70($out) + lea 0x80($out),$out # size optimization + movdqu 0x30($inp),$xt3 + pxor 0x20(%rsp),$xt0 + pxor $xb2,$xt1 + pxor $xc2,$xt2 + pxor $xd2,$xt3 + movdqu $xt0,0x00($out) + movdqu $xt1,0x10($out) + movdqu $xt2,0x20($out) + movdqu $xt3,0x30($out) + je .Ldone4x + + movdqa 0x30(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x40($inp),$inp # inp+=64*3 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb3,0x10(%rsp) + lea 0x40($out),$out # out+=64*3 + movdqa $xc3,0x20(%rsp) + sub \$192,$len # len-=64*3 + movdqa $xd3,0x30(%rsp) + +.Loop_tail4x: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail4x + +.Ldone4x: +___ +$code.=<<___ if ($win64); + lea 0x140+0x30(%rsp),%r11 + movaps -0x30(%r11),%xmm6 + movaps -0x20(%r11),%xmm7 + movaps -0x10(%r11),%xmm8 + movaps 0x00(%r11),%xmm9 + movaps 0x10(%r11),%xmm10 + movaps 0x20(%r11),%xmm11 + movaps 0x30(%r11),%xmm12 + movaps 0x40(%r11),%xmm13 + movaps 0x50(%r11),%xmm14 + movaps 0x60(%r11),%xmm15 +___ +$code.=<<___; + add \$0x148+$xframe,%rsp + ret +.size ChaCha20_4x,.-ChaCha20_4x +___ +} + +######################################################################## +# AVX2 code path +if ($avx>1) { +my ($xb0,$xb1,$xb2,$xb3, $xd0,$xd1,$xd2,$xd3, + $xa0,$xa1,$xa2,$xa3, $xt0,$xt1,$xt2,$xt3)=map("%ymm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3); + +sub AVX2_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3); +my @x=map("\"$_\"",@xx); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + ( + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", # Q1 + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpshufb (@x[$d0],@x[$d0],$t1)", + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", # Q2 + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpshufb (@x[$d1],@x[$d1],$t1)", + + "&vpaddd ($xc,$xc,@x[$d0])", + "&vpxor (@x[$b0],$xc,@x[$b0])", + "&vpslld ($t0,@x[$b0],12)", + "&vpsrld (@x[$b0],@x[$b0],20)", + "&vpor (@x[$b0],$t0,@x[$b0])", + "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip) + "&vpaddd ($xc_,$xc_,@x[$d1])", + "&vpxor (@x[$b1],$xc_,@x[$b1])", + "&vpslld ($t1,@x[$b1],12)", + "&vpsrld (@x[$b1],@x[$b1],20)", + "&vpor (@x[$b1],$t1,@x[$b1])", + + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpshufb (@x[$d0],@x[$d0],$t0)", + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpshufb (@x[$d1],@x[$d1],$t0)", + + "&vpaddd ($xc,$xc,@x[$d0])", + "&vpxor (@x[$b0],$xc,@x[$b0])", + "&vpslld ($t1,@x[$b0],7)", + "&vpsrld (@x[$b0],@x[$b0],25)", + "&vpor (@x[$b0],$t1,@x[$b0])", + "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip) + "&vpaddd ($xc_,$xc_,@x[$d1])", + "&vpxor (@x[$b1],$xc_,@x[$b1])", + "&vpslld ($t0,@x[$b1],7)", + "&vpsrld (@x[$b1],@x[$b1],25)", + "&vpor (@x[$b1],$t0,@x[$b1])", + + "&vmovdqa (\"`32*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's + "&vmovdqa (\"`32*($c1-8)`(%rsp)\",$xc_)", + "&vmovdqa ($xc,\"`32*($c2-8)`(%rsp)\")", + "&vmovdqa ($xc_,\"`32*($c3-8)`(%rsp)\")", + + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", # Q3 + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpshufb (@x[$d2],@x[$d2],$t1)", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", # Q4 + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vpshufb (@x[$d3],@x[$d3],$t1)", + + "&vpaddd ($xc,$xc,@x[$d2])", + "&vpxor (@x[$b2],$xc,@x[$b2])", + "&vpslld ($t0,@x[$b2],12)", + "&vpsrld (@x[$b2],@x[$b2],20)", + "&vpor (@x[$b2],$t0,@x[$b2])", + "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip) + "&vpaddd ($xc_,$xc_,@x[$d3])", + "&vpxor (@x[$b3],$xc_,@x[$b3])", + "&vpslld ($t1,@x[$b3],12)", + "&vpsrld (@x[$b3],@x[$b3],20)", + "&vpor (@x[$b3],$t1,@x[$b3])", + + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpshufb (@x[$d2],@x[$d2],$t0)", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vpshufb (@x[$d3],@x[$d3],$t0)", + + "&vpaddd ($xc,$xc,@x[$d2])", + "&vpxor (@x[$b2],$xc,@x[$b2])", + "&vpslld ($t1,@x[$b2],7)", + "&vpsrld (@x[$b2],@x[$b2],25)", + "&vpor (@x[$b2],$t1,@x[$b2])", + "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip) + "&vpaddd ($xc_,$xc_,@x[$d3])", + "&vpxor (@x[$b3],$xc_,@x[$b3])", + "&vpslld ($t0,@x[$b3],7)", + "&vpsrld (@x[$b3],@x[$b3],25)", + "&vpor (@x[$b3],$t0,@x[$b3])" + ); +} + +my $xframe = $win64 ? 0xb0 : 8; + +$code.=<<___; +.type ChaCha20_8x,\@function,5 +.align 32 +ChaCha20_8x: +.LChaCha20_8x: + mov %rsp,%r10 + sub \$0x280+$xframe,%rsp + and \$-32,%rsp +___ +$code.=<<___ if ($win64); + lea 0x290+0x30(%rsp),%r11 + movaps %xmm6,-0x30(%r11) + movaps %xmm7,-0x20(%r11) + movaps %xmm8,-0x10(%r11) + movaps %xmm9,0x00(%r11) + movaps %xmm10,0x10(%r11) + movaps %xmm11,0x20(%r11) + movaps %xmm12,0x30(%r11) + movaps %xmm13,0x40(%r11) + movaps %xmm14,0x50(%r11) + movaps %xmm15,0x60(%r11) +___ +$code.=<<___; + vzeroupper + mov %r10,0x280(%rsp) + + ################ stack layout + # +0x00 SIMD equivalent of @x[8-12] + # ... + # +0x80 constant copy of key[0-2] smashed by lanes + # ... + # +0x200 SIMD counters (with nonce smashed by lanes) + # ... + # +0x280 saved %rsp + + vbroadcasti128 .Lsigma(%rip),$xa3 # key[0] + vbroadcasti128 ($key),$xb3 # key[1] + vbroadcasti128 16($key),$xt3 # key[2] + vbroadcasti128 ($counter),$xd3 # key[3] + lea 0x100(%rsp),%rcx # size optimization + lea 0x200(%rsp),%rax # size optimization + lea .Lrot16(%rip),%r10 + lea .Lrot24(%rip),%r11 + + vpshufd \$0x00,$xa3,$xa0 # smash key by lanes... + vpshufd \$0x55,$xa3,$xa1 + vmovdqa $xa0,0x80-0x100(%rcx) # ... and offload + vpshufd \$0xaa,$xa3,$xa2 + vmovdqa $xa1,0xa0-0x100(%rcx) + vpshufd \$0xff,$xa3,$xa3 + vmovdqa $xa2,0xc0-0x100(%rcx) + vmovdqa $xa3,0xe0-0x100(%rcx) + + vpshufd \$0x00,$xb3,$xb0 + vpshufd \$0x55,$xb3,$xb1 + vmovdqa $xb0,0x100-0x100(%rcx) + vpshufd \$0xaa,$xb3,$xb2 + vmovdqa $xb1,0x120-0x100(%rcx) + vpshufd \$0xff,$xb3,$xb3 + vmovdqa $xb2,0x140-0x100(%rcx) + vmovdqa $xb3,0x160-0x100(%rcx) + + vpshufd \$0x00,$xt3,$xt0 # "xc0" + vpshufd \$0x55,$xt3,$xt1 # "xc1" + vmovdqa $xt0,0x180-0x200(%rax) + vpshufd \$0xaa,$xt3,$xt2 # "xc2" + vmovdqa $xt1,0x1a0-0x200(%rax) + vpshufd \$0xff,$xt3,$xt3 # "xc3" + vmovdqa $xt2,0x1c0-0x200(%rax) + vmovdqa $xt3,0x1e0-0x200(%rax) + + vpshufd \$0x00,$xd3,$xd0 + vpshufd \$0x55,$xd3,$xd1 + vpaddd .Lincy(%rip),$xd0,$xd0 # don't save counters yet + vpshufd \$0xaa,$xd3,$xd2 + vmovdqa $xd1,0x220-0x200(%rax) + vpshufd \$0xff,$xd3,$xd3 + vmovdqa $xd2,0x240-0x200(%rax) + vmovdqa $xd3,0x260-0x200(%rax) + + jmp .Loop_enter8x + +.align 32 +.Loop_outer8x: + vmovdqa 0x80-0x100(%rcx),$xa0 # re-load smashed key + vmovdqa 0xa0-0x100(%rcx),$xa1 + vmovdqa 0xc0-0x100(%rcx),$xa2 + vmovdqa 0xe0-0x100(%rcx),$xa3 + vmovdqa 0x100-0x100(%rcx),$xb0 + vmovdqa 0x120-0x100(%rcx),$xb1 + vmovdqa 0x140-0x100(%rcx),$xb2 + vmovdqa 0x160-0x100(%rcx),$xb3 + vmovdqa 0x180-0x200(%rax),$xt0 # "xc0" + vmovdqa 0x1a0-0x200(%rax),$xt1 # "xc1" + vmovdqa 0x1c0-0x200(%rax),$xt2 # "xc2" + vmovdqa 0x1e0-0x200(%rax),$xt3 # "xc3" + vmovdqa 0x200-0x200(%rax),$xd0 + vmovdqa 0x220-0x200(%rax),$xd1 + vmovdqa 0x240-0x200(%rax),$xd2 + vmovdqa 0x260-0x200(%rax),$xd3 + vpaddd .Leight(%rip),$xd0,$xd0 # next SIMD counters + +.Loop_enter8x: + vmovdqa $xt2,0x40(%rsp) # SIMD equivalent of "@x[10]" + vmovdqa $xt3,0x60(%rsp) # SIMD equivalent of "@x[11]" + vbroadcasti128 (%r10),$xt3 + vmovdqa $xd0,0x200-0x200(%rax) # save SIMD counters + mov \$10,%eax + jmp .Loop8x + +.align 32 +.Loop8x: +___ + foreach (&AVX2_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&AVX2_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop8x + + lea 0x200(%rsp),%rax # size optimization + vpaddd 0x80-0x100(%rcx),$xa0,$xa0 # accumulate key + vpaddd 0xa0-0x100(%rcx),$xa1,$xa1 + vpaddd 0xc0-0x100(%rcx),$xa2,$xa2 + vpaddd 0xe0-0x100(%rcx),$xa3,$xa3 + + vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data + vpunpckldq $xa3,$xa2,$xt3 + vpunpckhdq $xa1,$xa0,$xa0 + vpunpckhdq $xa3,$xa2,$xa2 + vpunpcklqdq $xt3,$xt2,$xa1 # "a0" + vpunpckhqdq $xt3,$xt2,$xt2 # "a1" + vpunpcklqdq $xa2,$xa0,$xa3 # "a2" + vpunpckhqdq $xa2,$xa0,$xa0 # "a3" +___ + ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2); +$code.=<<___; + vpaddd 0x100-0x100(%rcx),$xb0,$xb0 + vpaddd 0x120-0x100(%rcx),$xb1,$xb1 + vpaddd 0x140-0x100(%rcx),$xb2,$xb2 + vpaddd 0x160-0x100(%rcx),$xb3,$xb3 + + vpunpckldq $xb1,$xb0,$xt2 + vpunpckldq $xb3,$xb2,$xt3 + vpunpckhdq $xb1,$xb0,$xb0 + vpunpckhdq $xb3,$xb2,$xb2 + vpunpcklqdq $xt3,$xt2,$xb1 # "b0" + vpunpckhqdq $xt3,$xt2,$xt2 # "b1" + vpunpcklqdq $xb2,$xb0,$xb3 # "b2" + vpunpckhqdq $xb2,$xb0,$xb0 # "b3" +___ + ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2); +$code.=<<___; + vperm2i128 \$0x20,$xb0,$xa0,$xt3 # "de-interlace" further + vperm2i128 \$0x31,$xb0,$xa0,$xb0 + vperm2i128 \$0x20,$xb1,$xa1,$xa0 + vperm2i128 \$0x31,$xb1,$xa1,$xb1 + vperm2i128 \$0x20,$xb2,$xa2,$xa1 + vperm2i128 \$0x31,$xb2,$xa2,$xb2 + vperm2i128 \$0x20,$xb3,$xa3,$xa2 + vperm2i128 \$0x31,$xb3,$xa3,$xb3 +___ + ($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3); + my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1); +$code.=<<___; + vmovdqa $xa0,0x00(%rsp) # offload $xaN + vmovdqa $xa1,0x20(%rsp) + vmovdqa 0x40(%rsp),$xc2 # $xa0 + vmovdqa 0x60(%rsp),$xc3 # $xa1 + + vpaddd 0x180-0x200(%rax),$xc0,$xc0 + vpaddd 0x1a0-0x200(%rax),$xc1,$xc1 + vpaddd 0x1c0-0x200(%rax),$xc2,$xc2 + vpaddd 0x1e0-0x200(%rax),$xc3,$xc3 + + vpunpckldq $xc1,$xc0,$xt2 + vpunpckldq $xc3,$xc2,$xt3 + vpunpckhdq $xc1,$xc0,$xc0 + vpunpckhdq $xc3,$xc2,$xc2 + vpunpcklqdq $xt3,$xt2,$xc1 # "c0" + vpunpckhqdq $xt3,$xt2,$xt2 # "c1" + vpunpcklqdq $xc2,$xc0,$xc3 # "c2" + vpunpckhqdq $xc2,$xc0,$xc0 # "c3" +___ + ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2); +$code.=<<___; + vpaddd 0x200-0x200(%rax),$xd0,$xd0 + vpaddd 0x220-0x200(%rax),$xd1,$xd1 + vpaddd 0x240-0x200(%rax),$xd2,$xd2 + vpaddd 0x260-0x200(%rax),$xd3,$xd3 + + vpunpckldq $xd1,$xd0,$xt2 + vpunpckldq $xd3,$xd2,$xt3 + vpunpckhdq $xd1,$xd0,$xd0 + vpunpckhdq $xd3,$xd2,$xd2 + vpunpcklqdq $xt3,$xt2,$xd1 # "d0" + vpunpckhqdq $xt3,$xt2,$xt2 # "d1" + vpunpcklqdq $xd2,$xd0,$xd3 # "d2" + vpunpckhqdq $xd2,$xd0,$xd0 # "d3" +___ + ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2); +$code.=<<___; + vperm2i128 \$0x20,$xd0,$xc0,$xt3 # "de-interlace" further + vperm2i128 \$0x31,$xd0,$xc0,$xd0 + vperm2i128 \$0x20,$xd1,$xc1,$xc0 + vperm2i128 \$0x31,$xd1,$xc1,$xd1 + vperm2i128 \$0x20,$xd2,$xc2,$xc1 + vperm2i128 \$0x31,$xd2,$xc2,$xd2 + vperm2i128 \$0x20,$xd3,$xc3,$xc2 + vperm2i128 \$0x31,$xd3,$xc3,$xd3 +___ + ($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3); + ($xb0,$xb1,$xb2,$xb3,$xc0,$xc1,$xc2,$xc3)= + ($xc0,$xc1,$xc2,$xc3,$xb0,$xb1,$xb2,$xb3); + ($xa0,$xa1)=($xt2,$xt3); +$code.=<<___; + vmovdqa 0x00(%rsp),$xa0 # $xaN was offloaded, remember? + vmovdqa 0x20(%rsp),$xa1 + + cmp \$64*8,$len + jb .Ltail8x + + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa1,$xa1 + vpxor 0x20($inp),$xb1,$xb1 + vpxor 0x40($inp),$xc1,$xc1 + vpxor 0x60($inp),$xd1,$xd1 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa1,0x00($out) + vmovdqu $xb1,0x20($out) + vmovdqu $xc1,0x40($out) + vmovdqu $xd1,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa2,$xa2 + vpxor 0x20($inp),$xb2,$xb2 + vpxor 0x40($inp),$xc2,$xc2 + vpxor 0x60($inp),$xd2,$xd2 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa2,0x00($out) + vmovdqu $xb2,0x20($out) + vmovdqu $xc2,0x40($out) + vmovdqu $xd2,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa3,$xa3 + vpxor 0x20($inp),$xb3,$xb3 + vpxor 0x40($inp),$xc3,$xc3 + vpxor 0x60($inp),$xd3,$xd3 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa3,0x00($out) + vmovdqu $xb3,0x20($out) + vmovdqu $xc3,0x40($out) + vmovdqu $xd3,0x60($out) + lea 0x80($out),$out # size optimization + + sub \$64*8,$len + jnz .Loop_outer8x + + jmp .Ldone8x + +.Ltail8x: + cmp \$448,$len + jae .L448_or_more8x + cmp \$384,$len + jae .L384_or_more8x + cmp \$320,$len + jae .L320_or_more8x + cmp \$256,$len + jae .L256_or_more8x + cmp \$192,$len + jae .L192_or_more8x + cmp \$128,$len + jae .L128_or_more8x + cmp \$64,$len + jae .L64_or_more8x + + xor %r10,%r10 + vmovdqa $xa0,0x00(%rsp) + vmovdqa $xb0,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L64_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + je .Ldone8x + + lea 0x40($inp),$inp # inp+=64*1 + xor %r10,%r10 + vmovdqa $xc0,0x00(%rsp) + lea 0x40($out),$out # out+=64*1 + sub \$64,$len # len-=64*1 + vmovdqa $xd0,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L128_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + je .Ldone8x + + lea 0x80($inp),$inp # inp+=64*2 + xor %r10,%r10 + vmovdqa $xa1,0x00(%rsp) + lea 0x80($out),$out # out+=64*2 + sub \$128,$len # len-=64*2 + vmovdqa $xb1,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L192_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + je .Ldone8x + + lea 0xc0($inp),$inp # inp+=64*3 + xor %r10,%r10 + vmovdqa $xc1,0x00(%rsp) + lea 0xc0($out),$out # out+=64*3 + sub \$192,$len # len-=64*3 + vmovdqa $xd1,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L256_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + je .Ldone8x + + lea 0x100($inp),$inp # inp+=64*4 + xor %r10,%r10 + vmovdqa $xa2,0x00(%rsp) + lea 0x100($out),$out # out+=64*4 + sub \$256,$len # len-=64*4 + vmovdqa $xb2,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L320_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + je .Ldone8x + + lea 0x140($inp),$inp # inp+=64*5 + xor %r10,%r10 + vmovdqa $xc2,0x00(%rsp) + lea 0x140($out),$out # out+=64*5 + sub \$320,$len # len-=64*5 + vmovdqa $xd2,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L384_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vpxor 0x140($inp),$xc2,$xc2 + vpxor 0x160($inp),$xd2,$xd2 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + vmovdqu $xc2,0x140($out) + vmovdqu $xd2,0x160($out) + je .Ldone8x + + lea 0x180($inp),$inp # inp+=64*6 + xor %r10,%r10 + vmovdqa $xa3,0x00(%rsp) + lea 0x180($out),$out # out+=64*6 + sub \$384,$len # len-=64*6 + vmovdqa $xb3,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L448_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vpxor 0x140($inp),$xc2,$xc2 + vpxor 0x160($inp),$xd2,$xd2 + vpxor 0x180($inp),$xa3,$xa3 + vpxor 0x1a0($inp),$xb3,$xb3 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + vmovdqu $xc2,0x140($out) + vmovdqu $xd2,0x160($out) + vmovdqu $xa3,0x180($out) + vmovdqu $xb3,0x1a0($out) + je .Ldone8x + + lea 0x1c0($inp),$inp # inp+=64*7 + xor %r10,%r10 + vmovdqa $xc3,0x00(%rsp) + lea 0x1c0($out),$out # out+=64*7 + sub \$448,$len # len-=64*7 + vmovdqa $xd3,0x20(%rsp) + +.Loop_tail8x: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail8x + +.Ldone8x: + vzeroall +___ +$code.=<<___ if ($win64); + lea 0x290+0x30(%rsp),%r11 + movaps -0x30(%r11),%xmm6 + movaps -0x20(%r11),%xmm7 + movaps -0x10(%r11),%xmm8 + movaps 0x00(%r11),%xmm9 + movaps 0x10(%r11),%xmm10 + movaps 0x20(%r11),%xmm11 + movaps 0x30(%r11),%xmm12 + movaps 0x40(%r11),%xmm13 + movaps 0x50(%r11),%xmm14 + movaps 0x60(%r11),%xmm15 +___ +$code.=<<___; + mov 0x280(%rsp),%rsp + ret +.size ChaCha20_8x,.-ChaCha20_8x +___ +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/%x#%y/%x/go; + + print $_,"\n"; +} + +close STDOUT; diff --git a/external/boringssl/crypto/chacha/chacha.c b/external/boringssl/crypto/chacha/chacha.c new file mode 100644 index 0000000000..156208945c --- /dev/null +++ b/external/boringssl/crypto/chacha/chacha.c @@ -0,0 +1,170 @@ +/* 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 + +#include +#include + +#include + +#include "../internal.h" + + +#define U8TO32_LITTLE(p) \ + (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ + ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24)) + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) + +/* ChaCha20_ctr32 is defined in asm/chacha-*.pl. */ +void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len, + const uint32_t key[8], const uint32_t counter[4]); + +void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len, + const uint8_t key[32], const uint8_t nonce[12], + uint32_t counter) { + assert(!buffers_alias(out, in_len, in, in_len) || in == out); + + uint32_t counter_nonce[4]; counter_nonce[0] = counter; + counter_nonce[1] = U8TO32_LITTLE(nonce + 0); + counter_nonce[2] = U8TO32_LITTLE(nonce + 4); + counter_nonce[3] = U8TO32_LITTLE(nonce + 8); + + const uint32_t *key_ptr = (const uint32_t *)key; +#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) + /* The assembly expects the key to be four-byte aligned. */ + uint32_t key_u32[8]; + if ((((uintptr_t)key) & 3) != 0) { + key_u32[0] = U8TO32_LITTLE(key + 0); + key_u32[1] = U8TO32_LITTLE(key + 4); + key_u32[2] = U8TO32_LITTLE(key + 8); + key_u32[3] = U8TO32_LITTLE(key + 12); + key_u32[4] = U8TO32_LITTLE(key + 16); + key_u32[5] = U8TO32_LITTLE(key + 20); + key_u32[6] = U8TO32_LITTLE(key + 24); + key_u32[7] = U8TO32_LITTLE(key + 28); + + key_ptr = key_u32; + } +#endif + + ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce); +} + +#else + +/* 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; \ + } + +/* 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); + +/* 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[12], + uint32_t counter) { + assert(!buffers_alias(out, in_len, in, in_len) || in == out); + + uint32_t input[16]; + uint8_t buf[64]; + size_t todo, i; + + 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] = U8TO32_LITTLE(nonce + 0); + input[14] = U8TO32_LITTLE(nonce + 4); + input[15] = U8TO32_LITTLE(nonce + 8); + + 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]++; + } +} + +#endif diff --git a/external/boringssl/crypto/chacha/chacha_test.cc b/external/boringssl/crypto/chacha/chacha_test.cc new file mode 100644 index 0000000000..0a5972f7d4 --- /dev/null +++ b/external/boringssl/crypto/chacha/chacha_test.cc @@ -0,0 +1,248 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include + +#include +#include + + +static const uint8_t kKey[32] = { + 0x98, 0xbe, 0xf1, 0x46, 0x9b, 0xe7, 0x26, 0x98, 0x37, 0xa4, 0x5b, + 0xfb, 0xc9, 0x2a, 0x5a, 0x6a, 0xc7, 0x62, 0x50, 0x7c, 0xf9, 0x64, + 0x43, 0xbf, 0x33, 0xb9, 0x6b, 0x1b, 0xd4, 0xc6, 0xf8, 0xf6, +}; + +static const uint8_t kNonce[12] = { + 0x44, 0xe7, 0x92, 0xd6, 0x33, 0x35, 0xab, 0xb1, 0x58, 0x2e, 0x92, 0x53, +}; + +static uint32_t kCounter = 42; + +static const uint8_t kInput[] = { + 0x58, 0x28, 0xd5, 0x30, 0x36, 0x2c, 0x60, 0x55, 0x29, 0xf8, 0xe1, 0x8c, + 0xae, 0x15, 0x15, 0x26, 0xf2, 0x3a, 0x73, 0xa0, 0xf3, 0x12, 0xa3, 0x88, + 0x5f, 0x2b, 0x74, 0x23, 0x3d, 0xc9, 0x05, 0x23, 0xc6, 0x54, 0x49, 0x1e, + 0x44, 0x88, 0x14, 0xd9, 0xda, 0x37, 0x15, 0xdc, 0xb7, 0xe4, 0x23, 0xb3, + 0x9d, 0x7e, 0x16, 0x68, 0x35, 0xfc, 0x02, 0x6d, 0xcc, 0x8a, 0xe5, 0xdd, + 0x5f, 0xe4, 0xd2, 0x56, 0x6f, 0x12, 0x9c, 0x9c, 0x7d, 0x6a, 0x38, 0x48, + 0xbd, 0xdf, 0xd9, 0xac, 0x1b, 0xa2, 0x4d, 0xc5, 0x43, 0x04, 0x3c, 0xd7, + 0x99, 0xe1, 0xa7, 0x13, 0x9c, 0x51, 0xc2, 0x6d, 0xf9, 0xcf, 0x07, 0x3b, + 0xe4, 0xbf, 0x93, 0xa3, 0xa9, 0xb4, 0xc5, 0xf0, 0x1a, 0xe4, 0x8d, 0x5f, + 0xc6, 0xc4, 0x7c, 0x69, 0x7a, 0xde, 0x1a, 0xc1, 0xc9, 0xcf, 0xc2, 0x4e, + 0x7a, 0x25, 0x2c, 0x32, 0xe9, 0x17, 0xba, 0x68, 0xf1, 0x37, 0x5d, 0x62, + 0x84, 0x46, 0xf5, 0x80, 0x7f, 0x1a, 0x71, 0xf7, 0xbe, 0x72, 0x4b, 0xb8, + 0x1c, 0xfe, 0x3e, 0xbd, 0xae, 0x0d, 0x73, 0x0d, 0x87, 0x4a, 0x31, 0xc3, + 0x3d, 0x46, 0x6f, 0xb3, 0xd7, 0x6b, 0xe3, 0xb8, 0x70, 0x17, 0x8e, 0x7a, + 0x6a, 0x0e, 0xbf, 0xa8, 0xbc, 0x2b, 0xdb, 0xfa, 0x4f, 0xb6, 0x26, 0x20, + 0xee, 0x63, 0xf0, 0x6d, 0x26, 0xac, 0x6a, 0x18, 0x37, 0x6e, 0x59, 0x81, + 0xd1, 0x60, 0xe6, 0x40, 0xd5, 0x6d, 0x68, 0xba, 0x8b, 0x65, 0x4a, 0xf9, + 0xf1, 0xae, 0x56, 0x24, 0x8f, 0xe3, 0x8e, 0xe7, 0x7e, 0x6f, 0xcf, 0x92, + 0xdf, 0xa9, 0x75, 0x3a, 0xd6, 0x2e, 0x1c, 0xaf, 0xf2, 0xd6, 0x8b, 0x39, + 0xad, 0xd2, 0x5d, 0xfb, 0xd7, 0xdf, 0x05, 0x57, 0x0d, 0xf7, 0xf6, 0x8f, + 0x2d, 0x14, 0xb0, 0x4e, 0x1a, 0x3c, 0x77, 0x04, 0xcd, 0x3c, 0x5c, 0x58, + 0x52, 0x10, 0x6f, 0xcf, 0x5c, 0x03, 0xc8, 0x5f, 0x85, 0x2b, 0x05, 0x82, + 0x60, 0xda, 0xcc, 0xcd, 0xd6, 0x88, 0xbf, 0xc0, 0x10, 0xb3, 0x6f, 0x54, + 0x54, 0x42, 0xbc, 0x4b, 0x77, 0x21, 0x4d, 0xee, 0x87, 0x45, 0x06, 0x4c, + 0x60, 0x38, 0xd2, 0x7e, 0x1d, 0x30, 0x6c, 0x55, 0xf0, 0x38, 0x80, 0x1c, + 0xde, 0x3d, 0xea, 0x68, 0x3e, 0xf6, 0x3e, 0x59, 0xcf, 0x0d, 0x08, 0xae, + 0x8c, 0x02, 0x0b, 0xc1, 0x72, 0x6a, 0xb4, 0x6d, 0xf3, 0xf7, 0xb3, 0xef, + 0x3a, 0xb1, 0x06, 0xf2, 0xf4, 0xd6, 0x69, 0x7b, 0x3e, 0xa2, 0x16, 0x31, + 0x31, 0x79, 0xb6, 0x33, 0xa9, 0xca, 0x8a, 0xa8, 0xbe, 0xf3, 0xe9, 0x38, + 0x28, 0xd1, 0xe1, 0x3b, 0x4e, 0x2e, 0x47, 0x35, 0xa4, 0x61, 0x14, 0x1e, + 0x42, 0x2c, 0x49, 0x55, 0xea, 0xe3, 0xb3, 0xce, 0x39, 0xd3, 0xb3, 0xef, + 0x4a, 0x4d, 0x78, 0x49, 0xbd, 0xf6, 0x7c, 0x0a, 0x2c, 0xd3, 0x26, 0xcb, + 0xd9, 0x6a, 0xad, 0x63, 0x93, 0xa7, 0x29, 0x92, 0xdc, 0x1f, 0xaf, 0x61, + 0x82, 0x80, 0x74, 0xb2, 0x9c, 0x4a, 0x86, 0x73, 0x50, 0xd8, 0xd1, 0xff, + 0xee, 0x1a, 0xe2, 0xdd, 0xa2, 0x61, 0xbd, 0x10, 0xc3, 0x5f, 0x67, 0x9f, + 0x29, 0xe4, 0xd3, 0x70, 0xe5, 0x67, 0x3a, 0xd2, 0x20, 0x00, 0xcc, 0x25, + 0x15, 0x96, 0x54, 0x45, 0x85, 0xed, 0x82, 0x88, 0x3b, 0x9f, 0x3b, 0xc3, + 0x04, 0xd4, 0x23, 0xb1, 0x0d, 0xdc, 0xc8, 0x26, 0x9d, 0x28, 0xb3, 0x25, + 0x4d, 0x52, 0xe5, 0x33, 0xf3, 0xed, 0x2c, 0xb8, 0x1a, 0xcf, 0xc3, 0x52, + 0xb4, 0x2f, 0xc7, 0x79, 0x96, 0x14, 0x7d, 0x72, 0x27, 0x72, 0x85, 0xea, + 0x6d, 0x41, 0xa0, 0x22, 0x13, 0x6d, 0x06, 0x83, 0xa4, 0xdd, 0x0f, 0x69, + 0xd2, 0x01, 0xcd, 0xc6, 0xb8, 0x64, 0x5c, 0x2c, 0x79, 0xd1, 0xc7, 0xd3, + 0x31, 0xdb, 0x2c, 0xff, 0xda, 0xd0, 0x69, 0x31, 0xad, 0x83, 0x5f, 0xed, + 0x6a, 0x97, 0xe4, 0x00, 0x43, 0xb0, 0x2e, 0x97, 0xae, 0x00, 0x5f, 0x5c, + 0xb9, 0xe8, 0x39, 0x80, 0x10, 0xca, 0x0c, 0xfa, 0xf0, 0xb5, 0xcd, 0xaa, + 0x27, 0x11, 0x60, 0xd9, 0x21, 0x86, 0x93, 0x91, 0x9f, 0x2d, 0x1a, 0x8e, + 0xde, 0x0b, 0xb5, 0xcb, 0x05, 0x24, 0x30, 0x45, 0x4d, 0x11, 0x75, 0xfd, + 0xe5, 0xa0, 0xa9, 0x4e, 0x3a, 0x8c, 0x3b, 0x52, 0x5a, 0x37, 0x18, 0x05, + 0x4a, 0x7a, 0x09, 0x6a, 0xe6, 0xd5, 0xa9, 0xa6, 0x71, 0x47, 0x4c, 0x50, + 0xe1, 0x3e, 0x8a, 0x21, 0x2b, 0x4f, 0x0e, 0xe3, 0xcb, 0x72, 0xc5, 0x28, + 0x3e, 0x5a, 0x33, 0xec, 0x48, 0x92, 0x2e, 0xa1, 0x24, 0x57, 0x09, 0x0f, + 0x01, 0x85, 0x3b, 0x34, 0x39, 0x7e, 0xc7, 0x90, 0x62, 0xe2, 0xdc, 0x5d, + 0x0a, 0x2c, 0x51, 0x26, 0x95, 0x3a, 0x95, 0x92, 0xa5, 0x39, 0x8f, 0x0c, + 0x83, 0x0b, 0x9d, 0x38, 0xab, 0x98, 0x2a, 0xc4, 0x01, 0xc4, 0x0d, 0x77, + 0x13, 0xcb, 0xca, 0xf1, 0x28, 0x31, 0x52, 0x75, 0x27, 0x2c, 0xf0, 0x04, + 0x86, 0xc8, 0xf3, 0x3d, 0xf2, 0x9d, 0x8f, 0x55, 0x52, 0x40, 0x3f, 0xaa, + 0x22, 0x7f, 0xe7, 0x69, 0x3b, 0xee, 0x44, 0x09, 0xde, 0xff, 0xb0, 0x69, + 0x3a, 0xae, 0x74, 0xe9, 0x9d, 0x33, 0xae, 0x8b, 0x6d, 0x60, 0x04, 0xff, + 0x53, 0x3f, 0x88, 0xe9, 0x63, 0x9b, 0xb1, 0x6d, 0x2c, 0x22, 0x15, 0x5a, + 0x15, 0xd9, 0xe5, 0xcb, 0x03, 0x78, 0x3c, 0xca, 0x59, 0x8c, 0xc8, 0xc2, + 0x86, 0xff, 0xd2, 0x79, 0xd6, 0xc6, 0xec, 0x5b, 0xbb, 0xa0, 0xae, 0x01, + 0x20, 0x09, 0x2e, 0x38, 0x5d, 0xda, 0x5d, 0xe0, 0x59, 0x4e, 0xe5, 0x8b, + 0x84, 0x8f, 0xb6, 0xe0, 0x56, 0x9f, 0x21, 0xa1, 0xcf, 0xb2, 0x0f, 0x2c, + 0x93, 0xf8, 0xcf, 0x37, 0xc1, 0x9f, 0x32, 0x98, 0x21, 0x65, 0x52, 0x66, + 0x6e, 0xd3, 0x71, 0x98, 0x55, 0xb9, 0x46, 0x9f, 0x1a, 0x35, 0xc4, 0x47, + 0x69, 0x62, 0x70, 0x4b, 0x77, 0x9e, 0xe4, 0x21, 0xe6, 0x32, 0x5a, 0x26, + 0x05, 0xba, 0x57, 0x53, 0xd7, 0x9b, 0x55, 0x3c, 0xbb, 0x53, 0x79, 0x60, + 0x9c, 0xc8, 0x4d, 0xf7, 0xf5, 0x1d, 0x54, 0x02, 0x91, 0x68, 0x0e, 0xaa, + 0xca, 0x5a, 0x78, 0x0c, 0x28, 0x9a, 0xc3, 0xac, 0x49, 0xc0, 0xf4, 0x85, + 0xee, 0x59, 0x76, 0x7e, 0x28, 0x4e, 0xf1, 0x5c, 0x63, 0xf7, 0xce, 0x0e, + 0x2c, 0x21, 0xa0, 0x58, 0xe9, 0x01, 0xfd, 0xeb, 0xd1, 0xaf, 0xe6, 0xef, + 0x93, 0xb3, 0x95, 0x51, 0x60, 0xa2, 0x74, 0x40, 0x15, 0xe5, 0xf4, 0x0a, + 0xca, 0x6d, 0x9a, 0x37, 0x42, 0x4d, 0x5a, 0x58, 0x49, 0x0f, 0xe9, 0x02, + 0xfc, 0x77, 0xd8, 0x59, 0xde, 0xdd, 0xad, 0x4b, 0x99, 0x2e, 0x64, 0x73, + 0xad, 0x42, 0x2f, 0xf3, 0x2c, 0x0d, 0x49, 0xe4, 0x2e, 0x6c, 0xa4, 0x73, + 0x75, 0x18, 0x14, 0x85, 0xbb, 0x64, 0xb4, 0xa1, 0xb0, 0x6e, 0x01, 0xc0, + 0xcf, 0x17, 0x9c, 0xc5, 0x28, 0xc3, 0x2d, 0x6c, 0x17, 0x2a, 0x3d, 0x06, + 0x5c, 0xf3, 0xb4, 0x49, 0x75, 0xad, 0x17, 0x69, 0xd4, 0xca, 0x65, 0xae, + 0x44, 0x71, 0xa5, 0xf6, 0x0d, 0x0f, 0x8e, 0x37, 0xc7, 0x43, 0xce, 0x6b, + 0x08, 0xe9, 0xd1, 0x34, 0x48, 0x8f, 0xc9, 0xfc, 0xf3, 0x5d, 0x2d, 0xec, + 0x62, 0xd3, 0xf0, 0xb3, 0xfe, 0x2e, 0x40, 0x55, 0x76, 0x54, 0xc7, 0xb4, + 0x61, 0x16, 0xcc, 0x7c, 0x1c, 0x19, 0x24, 0xe6, 0x4d, 0xd4, 0xc3, 0x77, + 0x67, 0x1f, 0x3c, 0x74, 0x79, 0xa1, 0xf8, 0x85, 0x88, 0x1d, 0x6f, 0xa4, + 0x7e, 0x2c, 0x21, 0x9f, 0x49, 0xf5, 0xaa, 0x4e, 0xf3, 0x4a, 0xfa, 0x9d, + 0xbe, 0xf6, 0xce, 0xda, 0xb5, 0xab, 0x39, 0xbd, 0x16, 0x41, 0xa9, 0x4a, + 0xac, 0x09, 0x01, 0xca, +}; +static const uint8_t kOutput[] = { + 0x54, 0x30, 0x6a, 0x13, 0xda, 0x59, 0x6b, 0x6d, 0x59, 0x49, 0xc8, 0xc5, + 0xab, 0x26, 0xd4, 0x8a, 0xad, 0xc0, 0x3d, 0xaf, 0x14, 0xb9, 0x15, 0xb8, + 0xca, 0xdf, 0x17, 0xa7, 0x03, 0xd3, 0xc5, 0x06, 0x01, 0xef, 0x21, 0xdd, + 0xa3, 0x0b, 0x9e, 0x48, 0xb8, 0x5e, 0x0b, 0x87, 0x9f, 0x95, 0x23, 0x68, + 0x85, 0x69, 0xd2, 0x5d, 0xaf, 0x57, 0xe9, 0x27, 0x11, 0x3d, 0x49, 0xfa, + 0xf1, 0x08, 0xcc, 0x15, 0xec, 0x1d, 0x19, 0x16, 0x12, 0x9b, 0xc8, 0x66, + 0x1f, 0xfa, 0x2c, 0x93, 0xf4, 0x99, 0x11, 0x27, 0x31, 0x0e, 0xd8, 0x46, + 0x47, 0x40, 0x11, 0x70, 0x01, 0xca, 0xe8, 0x5b, 0xc5, 0x91, 0xc8, 0x3a, + 0xdc, 0xaa, 0xf3, 0x4b, 0x80, 0xe5, 0xbc, 0x03, 0xd0, 0x89, 0x72, 0xbc, + 0xce, 0x2a, 0x76, 0x0c, 0xf5, 0xda, 0x4c, 0x10, 0x06, 0x35, 0x41, 0xb1, + 0xe6, 0xb4, 0xaa, 0x7a, 0xef, 0xf0, 0x62, 0x4a, 0xc5, 0x9f, 0x2c, 0xaf, + 0xb8, 0x2f, 0xd9, 0xd1, 0x01, 0x7a, 0x36, 0x2f, 0x3e, 0x83, 0xa5, 0xeb, + 0x81, 0x70, 0xa0, 0x57, 0x17, 0x46, 0xea, 0x9e, 0xcb, 0x0e, 0x74, 0xd3, + 0x44, 0x57, 0x1d, 0x40, 0x06, 0xf8, 0xb7, 0xcb, 0x5f, 0xf4, 0x79, 0xbd, + 0x11, 0x19, 0xd6, 0xee, 0xf8, 0xb0, 0xaa, 0xdd, 0x00, 0x62, 0xad, 0x3b, + 0x88, 0x9a, 0x88, 0x5b, 0x1b, 0x07, 0xc9, 0xae, 0x9e, 0xa6, 0x94, 0xe5, + 0x55, 0xdb, 0x45, 0x23, 0xb9, 0x2c, 0xcd, 0x29, 0xd3, 0x54, 0xc3, 0x88, + 0x1e, 0x5f, 0x52, 0xf2, 0x09, 0x00, 0x26, 0x26, 0x1a, 0xed, 0xf5, 0xc2, + 0xa9, 0x7d, 0xf9, 0x21, 0x5a, 0xaf, 0x6d, 0xab, 0x8e, 0x16, 0x84, 0x96, + 0xb5, 0x4f, 0xcf, 0x1e, 0xa3, 0xaf, 0x08, 0x9f, 0x79, 0x86, 0xc3, 0xbe, + 0x0c, 0x70, 0xcb, 0x8f, 0xf3, 0xc5, 0xf8, 0xe8, 0x4b, 0x21, 0x7d, 0x18, + 0xa9, 0xed, 0x8b, 0xfb, 0x6b, 0x5a, 0x6f, 0x26, 0x0b, 0x56, 0x04, 0x7c, + 0xfe, 0x0e, 0x1e, 0xc1, 0x3f, 0x82, 0xc5, 0x73, 0xbd, 0x53, 0x0c, 0xf0, + 0xe2, 0xc9, 0xf3, 0x3d, 0x1b, 0x6d, 0xba, 0x70, 0xc1, 0x6d, 0xb6, 0x00, + 0x28, 0xe1, 0xc4, 0x78, 0x62, 0x04, 0xda, 0x23, 0x86, 0xc3, 0xda, 0x74, + 0x3d, 0x7c, 0xd6, 0x76, 0x29, 0xb2, 0x27, 0x2e, 0xb2, 0x35, 0x42, 0x60, + 0x82, 0xcf, 0x30, 0x2c, 0x59, 0xe4, 0xe3, 0xd0, 0x74, 0x1f, 0x58, 0xe8, + 0xda, 0x47, 0x45, 0x73, 0x1c, 0x05, 0x93, 0xae, 0x75, 0xbe, 0x1f, 0x81, + 0xd8, 0xb7, 0xb3, 0xff, 0xfc, 0x8b, 0x52, 0x9e, 0xed, 0x8b, 0x37, 0x9f, + 0xe0, 0xb8, 0xa2, 0x66, 0xe1, 0x6a, 0xc5, 0x1f, 0x1d, 0xf0, 0xde, 0x3f, + 0x3d, 0xb0, 0x28, 0xf3, 0xaa, 0x4e, 0x4d, 0x31, 0xb0, 0x26, 0x79, 0x2b, + 0x08, 0x0f, 0xe9, 0x2f, 0x79, 0xb3, 0xc8, 0xdd, 0xa7, 0x89, 0xa8, 0xa8, + 0x1d, 0x59, 0x0e, 0x4f, 0x1e, 0x93, 0x1f, 0x70, 0x7f, 0x4e, 0x7e, 0xfe, + 0xb8, 0xca, 0x63, 0xe0, 0xa6, 0x05, 0xcc, 0xd7, 0xde, 0x2a, 0x49, 0x31, + 0x78, 0x5c, 0x5f, 0x44, 0xb2, 0x9b, 0x91, 0x99, 0x14, 0x29, 0x63, 0x09, + 0x12, 0xdd, 0x02, 0xd9, 0x7b, 0xe9, 0xf5, 0x12, 0x07, 0xd0, 0xe7, 0xe6, + 0xe8, 0xdd, 0xda, 0xa4, 0x73, 0xc4, 0x8e, 0xbd, 0x7b, 0xb7, 0xbb, 0xcb, + 0x83, 0x2f, 0x43, 0xf6, 0x1c, 0x50, 0xae, 0x9b, 0x2e, 0x52, 0x80, 0x18, + 0x85, 0xa8, 0x23, 0x52, 0x7a, 0x6a, 0xf7, 0x42, 0x36, 0xca, 0x91, 0x5a, + 0x3d, 0x2a, 0xa0, 0x35, 0x7d, 0x70, 0xfc, 0x4c, 0x18, 0x7c, 0x57, 0x72, + 0xcf, 0x9b, 0x29, 0xd6, 0xd0, 0xb4, 0xd7, 0xe6, 0x89, 0x70, 0x69, 0x22, + 0x5e, 0x45, 0x09, 0x4d, 0x49, 0x87, 0x84, 0x5f, 0x8a, 0x5f, 0xe4, 0x15, + 0xd3, 0xe3, 0x72, 0xaf, 0xb2, 0x30, 0x9c, 0xc1, 0xff, 0x8e, 0x6d, 0x2a, + 0x76, 0x9e, 0x08, 0x03, 0x7e, 0xe0, 0xc3, 0xc2, 0x97, 0x06, 0x6b, 0x33, + 0x2b, 0x08, 0xe3, 0xd5, 0x0b, 0xd8, 0x32, 0x67, 0x61, 0x10, 0xed, 0x6b, + 0xed, 0x50, 0xef, 0xd7, 0x1c, 0x1b, 0xe0, 0x6d, 0xa1, 0x64, 0x19, 0x34, + 0x2f, 0xe4, 0xe8, 0x54, 0xbf, 0x84, 0x0e, 0xdf, 0x0e, 0x8b, 0xd8, 0xdd, + 0x77, 0x96, 0xb8, 0x54, 0xab, 0xf2, 0x95, 0x59, 0x0d, 0x0d, 0x0a, 0x15, + 0x6e, 0x01, 0xf2, 0x24, 0xab, 0xa0, 0xd8, 0xdf, 0x38, 0xea, 0x97, 0x58, + 0x76, 0x88, 0xbe, 0xaf, 0x45, 0xe3, 0x56, 0x4f, 0x68, 0xe8, 0x4b, 0xe7, + 0x2b, 0x22, 0x18, 0x96, 0x82, 0x89, 0x25, 0x34, 0xd1, 0xdd, 0x08, 0xea, + 0x7e, 0x21, 0xef, 0x57, 0x55, 0x43, 0xf7, 0xfa, 0xca, 0x1c, 0xde, 0x99, + 0x2e, 0x8b, 0xd8, 0xc3, 0xcf, 0x89, 0x4d, 0xfc, 0x3b, 0x7d, 0x4a, 0xc9, + 0x99, 0xc4, 0x31, 0xb6, 0x7a, 0xae, 0xf8, 0x49, 0xb2, 0x46, 0xc1, 0x60, + 0x05, 0x75, 0xf3, 0x3d, 0xf2, 0xc9, 0x84, 0xa4, 0xb9, 0x8a, 0x87, 0x2a, + 0x87, 0x5c, 0x0a, 0xbc, 0x51, 0x7d, 0x9a, 0xf5, 0xc9, 0x24, 0x2d, 0x5e, + 0xe6, 0xc6, 0xe3, 0xcd, 0x7e, 0xe4, 0xaf, 0x8a, 0x6c, 0x00, 0x04, 0xc8, + 0xd7, 0xa5, 0xad, 0xfa, 0xb2, 0x08, 0x4a, 0x26, 0x9b, 0x7c, 0xd0, 0xc6, + 0x13, 0xb1, 0xb9, 0x65, 0x3f, 0x70, 0x30, 0xf9, 0x98, 0x9d, 0x87, 0x99, + 0x57, 0x71, 0x3e, 0xb1, 0xc3, 0x24, 0xf0, 0xa6, 0xa2, 0x60, 0x9d, 0x66, + 0xd2, 0x5f, 0xae, 0xe3, 0x94, 0x87, 0xea, 0xd1, 0xea, 0x0d, 0x2a, 0x77, + 0xef, 0x31, 0xcc, 0xeb, 0xf9, 0x0c, 0xdc, 0x9c, 0x12, 0x80, 0xbb, 0xb0, + 0x8e, 0xab, 0x9a, 0x04, 0xcd, 0x4b, 0x95, 0x4f, 0x7a, 0x0b, 0x53, 0x7c, + 0x16, 0xcc, 0x0e, 0xb1, 0x73, 0x10, 0xdd, 0xaa, 0x76, 0x94, 0x90, 0xd9, + 0x8b, 0x66, 0x41, 0x31, 0xed, 0x8c, 0x7d, 0x74, 0xc4, 0x33, 0xfa, 0xc3, + 0x43, 0x8d, 0x10, 0xbc, 0x84, 0x4d, 0x0e, 0x95, 0x32, 0xdf, 0x17, 0x43, + 0x6d, 0xd2, 0x5e, 0x12, 0xb9, 0xed, 0x33, 0xd9, 0x97, 0x6f, 0x4a, 0xcd, + 0xc3, 0xcd, 0x81, 0x34, 0xbe, 0x7e, 0xa2, 0xd0, 0xa7, 0x91, 0x5d, 0x90, + 0xf6, 0x5e, 0x4a, 0x25, 0x0f, 0xcc, 0x24, 0xeb, 0xe1, 0xe4, 0x62, 0x6c, + 0x8f, 0x45, 0x36, 0x97, 0x5d, 0xda, 0x20, 0x2b, 0x86, 0x00, 0x8c, 0x94, + 0xa9, 0x6a, 0x69, 0xb2, 0xe9, 0xbb, 0x82, 0x8e, 0x41, 0x95, 0xb4, 0xb7, + 0xf1, 0x55, 0x52, 0x30, 0x39, 0x48, 0xb3, 0x25, 0x82, 0xa9, 0x10, 0x27, + 0x89, 0xb5, 0xe5, 0x1f, 0xab, 0x72, 0x3c, 0x70, 0x08, 0xce, 0xe6, 0x61, + 0xbf, 0x19, 0xc8, 0x90, 0x2b, 0x29, 0x30, 0x3e, 0xb8, 0x4c, 0x33, 0xf0, + 0xf0, 0x15, 0x2e, 0xb7, 0x25, 0xca, 0x99, 0x4b, 0x6f, 0x4b, 0x41, 0x50, + 0xee, 0x56, 0x99, 0xcf, 0x2b, 0xa4, 0xc4, 0x7c, 0x5c, 0xa6, 0xd4, 0x67, + 0x04, 0x5c, 0x5d, 0x5f, 0x26, 0x9e, 0x0f, 0xe2, 0x58, 0x68, 0x4c, 0x30, + 0xcd, 0xef, 0x46, 0xdb, 0x37, 0x6f, 0xbb, 0xc4, 0x80, 0xca, 0x8a, 0x54, + 0x5d, 0x71, 0x9d, 0x0c, 0xe8, 0xb8, 0x2c, 0x10, 0x90, 0x44, 0xa4, 0x88, + 0x3f, 0xbc, 0x15, 0x3c, 0xd2, 0xca, 0x0e, 0xc3, 0xe4, 0x6e, 0xef, 0xb0, + 0xcb, 0xfd, 0x61, 0x7c, 0x27, 0xf2, 0x25, 0xea, 0x71, 0x6d, 0xf7, 0x49, + 0x9c, 0x81, 0x27, 0xf0, 0x61, 0x33, 0xcf, 0x55, 0x68, 0xd3, 0x73, 0xa4, + 0xed, 0x35, 0x65, 0x2a, 0xf2, 0x3e, 0xcf, 0x90, 0x98, 0x54, 0x6d, 0x95, + 0x6a, 0x0c, 0x9c, 0x24, 0x0e, 0xb4, 0xb7, 0x9b, 0x8d, 0x6e, 0x1c, 0xbc, + 0xeb, 0x17, 0x10, 0x86, 0xda, 0x91, 0x6d, 0x89, 0x4c, 0xeb, 0xf5, 0x50, + 0x8f, 0x40, 0xcf, 0x4a, +}; + +static_assert(sizeof(kInput) == sizeof(kOutput), + "Input and output lengths don't match."); + +static bool TestChaCha20(size_t len) { + std::unique_ptr buf(new uint8_t[len]); + CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter); + if (memcmp(buf.get(), kOutput, len) != 0) { + fprintf(stderr, "Mismatch at length %zu.\n", len); + return false; + } + + // Test in-place. + memcpy(buf.get(), kInput, len); + CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter); + if (memcmp(buf.get(), kOutput, len) != 0) { + fprintf(stderr, "Mismatch at length %zu, in-place.\n", len); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + // Run the test with the test vector at all lengths. + for (size_t len = 0; len <= sizeof(kInput); len++) { + if (!TestChaCha20(len)) { + return 1; + } + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/cipher/CMakeLists.txt b/external/boringssl/crypto/cipher/CMakeLists.txt new file mode 100644 index 0000000000..49e5c6d8ef --- /dev/null +++ b/external/boringssl/crypto/cipher/CMakeLists.txt @@ -0,0 +1,42 @@ +include_directories(../../include) + +add_library( + cipher + + OBJECT + + cipher.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 +) + +if(ENABLE_TESTS) +add_executable( + cipher_test + + cipher_test.cc + $ +) + +add_executable( + aead_test + + aead_test.cc + $ +) + +target_link_libraries(cipher_test crypto) +target_link_libraries(aead_test crypto) +add_dependencies(all_tests cipher_test aead_test) +endif() diff --git a/external/boringssl/crypto/cipher/aead.c b/external/boringssl/crypto/cipher/aead.c new file mode 100644 index 0000000000..57eecc1b89 --- /dev/null +++ b/external/boringssl/crypto/cipher/aead.c @@ -0,0 +1,162 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include + +#include "internal.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; } + +void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx) { + memset(ctx, 0, sizeof(EVP_AEAD_CTX)); +} + +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) { + if (!aead->init) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_DIRECTION_SET); + ctx->aead = NULL; + return 0; + } + return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len, + evp_aead_open); +} + +int EVP_AEAD_CTX_init_with_direction(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, + const uint8_t *key, size_t key_len, + size_t tag_len, + enum evp_aead_direction_t dir) { + if (key_len != aead->key_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_KEY_SIZE); + ctx->aead = NULL; + return 0; + } + + ctx->aead = aead; + + int ok; + if (aead->init) { + ok = aead->init(ctx, key, key_len, tag_len); + } else { + ok = aead->init_with_direction(ctx, key, key_len, tag_len, dir); + } + + if (!ok) { + ctx->aead = NULL; + } + + return ok; +} + +void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) { + if (ctx->aead == NULL) { + return; + } + ctx->aead->cleanup(ctx); + ctx->aead = NULL; +} + +/* check_alias returns 1 if |out| is compatible with |in| and 0 otherwise. If + * |in| and |out| alias, we require that |in| == |out|. */ +static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out, + size_t out_len) { + if (!buffers_alias(in, in_len, out, out_len)) { + return 1; + } + + return in == out; +} + +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, CIPHER_R_TOO_LARGE); + goto error; + } + + if (!check_alias(in, in_len, out, max_out_len)) { + OPENSSL_PUT_ERROR(CIPHER, 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, max_out_len)) { + OPENSSL_PUT_ERROR(CIPHER, 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; +} + +int EVP_AEAD_CTX_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) { + if (ctx->aead->get_rc4_state == NULL) { + return 0; + } + + return ctx->aead->get_rc4_state(ctx, out_key); +} + +int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_len) { + if (ctx->aead->get_iv == NULL) { + return 0; + } + + return ctx->aead->get_iv(ctx, out_iv, out_len); +} diff --git a/external/boringssl/crypto/cipher/aead_test.cc b/external/boringssl/crypto/cipher/aead_test.cc new file mode 100644 index 0000000000..8bad93f55e --- /dev/null +++ b/external/boringssl/crypto/cipher/aead_test.cc @@ -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. */ + +#include +#include + +#include + +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +// This program tests an AEAD against a series of test vectors from a file, +// using the FileTest format. As an example, here's a valid test case: +// +// KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4 +// NONCE: 978105dfce667bf4 +// IN: 6a4583908d +// AD: b654574932 +// CT: 5294265a60 +// TAG: 1d45758621762e061368e68868e2f929 + +static bool TestAEAD(FileTest *t, void *arg) { + const EVP_AEAD *aead = reinterpret_cast(arg); + + std::vector key, nonce, in, ad, ct, tag; + if (!t->GetBytes(&key, "KEY") || + !t->GetBytes(&nonce, "NONCE") || + !t->GetBytes(&in, "IN") || + !t->GetBytes(&ad, "AD") || + !t->GetBytes(&ct, "CT") || + !t->GetBytes(&tag, "TAG")) { + return false; + } + + ScopedEVP_AEAD_CTX ctx; + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_seal)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + std::vector out(in.size() + EVP_AEAD_max_overhead(aead)); + if (!t->HasAttribute("NO_SEAL")) { + size_t out_len; + if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(), + nonce.data(), nonce.size(), in.data(), in.size(), + ad.data(), ad.size())) { + t->PrintLine("Failed to run AEAD."); + return false; + } + out.resize(out_len); + + if (out.size() != ct.size() + tag.size()) { + t->PrintLine("Bad output length: %u vs %u.", (unsigned)out_len, + (unsigned)(ct.size() + tag.size())); + return false; + } + if (!t->ExpectBytesEqual(ct.data(), ct.size(), out.data(), ct.size()) || + !t->ExpectBytesEqual(tag.data(), tag.size(), out.data() + ct.size(), + tag.size())) { + return false; + } + } else { + out.resize(ct.size() + tag.size()); + memcpy(out.data(), ct.data(), ct.size()); + memcpy(out.data() + ct.size(), tag.data(), tag.size()); + } + + // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be + // reset after each operation. + ctx.Reset(); + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_open)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + std::vector out2(out.size()); + size_t out2_len; + int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(), + nonce.data(), nonce.size(), out.data(), + out.size(), ad.data(), ad.size()); + if (t->HasAttribute("FAILS")) { + if (ret) { + t->PrintLine("Decrypted bad data."); + return false; + } + ERR_clear_error(); + return true; + } + + if (!ret) { + t->PrintLine("Failed to decrypt."); + return false; + } + out2.resize(out2_len); + if (!t->ExpectBytesEqual(in.data(), in.size(), out2.data(), out2.size())) { + return false; + } + + // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be + // reset after each operation. + ctx.Reset(); + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_open)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + // Garbage at the end isn't ignored. + out.push_back(0); + out2.resize(out.size()); + if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(), + nonce.data(), nonce.size(), out.data(), out.size(), + ad.data(), ad.size())) { + t->PrintLine("Decrypted bad data with trailing garbage."); + return false; + } + ERR_clear_error(); + + // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be + // reset after each operation. + ctx.Reset(); + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_open)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + // Verify integrity is checked. + out[0] ^= 0x80; + out.resize(out.size() - 1); + out2.resize(out.size()); + if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(), + nonce.data(), nonce.size(), out.data(), out.size(), + ad.data(), ad.size())) { + t->PrintLine("Decrypted bad data with corrupted byte."); + return false; + } + ERR_clear_error(); + + return true; +} + +static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) { + EVP_AEAD_CTX ctx; + uint8_t key[128]; + + memset(key, 0, sizeof(key)); + const size_t key_len = EVP_AEAD_key_length(aead); + if (key_len > sizeof(key)) { + fprintf(stderr, "Key length of AEAD too long.\n"); + return 0; + } + + if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len, + 9999 /* a silly tag length to trigger an error */, + NULL /* ENGINE */) != 0) { + fprintf(stderr, "A silly tag length didn't trigger an error!\n"); + return 0; + } + ERR_clear_error(); + + /* Running a second, failed _init should not cause a memory leak. */ + if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len, + 9999 /* a silly tag length to trigger an error */, + NULL /* ENGINE */) != 0) { + fprintf(stderr, "A silly tag length didn't trigger an error!\n"); + return 0; + } + ERR_clear_error(); + + /* Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a + * no-op. */ + EVP_AEAD_CTX_cleanup(&ctx); + return 1; +} + +static bool TestWithAliasedBuffers(const EVP_AEAD *aead) { + const size_t key_len = EVP_AEAD_key_length(aead); + const size_t nonce_len = EVP_AEAD_nonce_length(aead); + const size_t max_overhead = EVP_AEAD_max_overhead(aead); + + std::vector key(key_len, 'a'); + ScopedEVP_AEAD_CTX ctx; + if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len, + EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) { + return false; + } + + static const uint8_t kPlaintext[260] = + "testing123456testing123456testing123456testing123456testing123456testing" + "123456testing123456testing123456testing123456testing123456testing123456t" + "esting123456testing123456testing123456testing123456testing123456testing1" + "23456testing123456testing123456testing12345"; + const std::vector offsets = { + 0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63, + 64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257, + }; + + std::vector nonce(nonce_len, 'b'); + std::vector valid_encryption(sizeof(kPlaintext) + max_overhead); + size_t valid_encryption_len; + if (!EVP_AEAD_CTX_seal( + ctx.get(), valid_encryption.data(), &valid_encryption_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len, + kPlaintext, sizeof(kPlaintext), nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n"); + return false; + } + + // Test with out != in which we expect to fail. + std::vector buffer(2 + valid_encryption_len); + uint8_t *in = buffer.data() + 1; + uint8_t *out1 = buffer.data(); + uint8_t *out2 = buffer.data() + 2; + + memcpy(in, kPlaintext, sizeof(kPlaintext)); + size_t out_len; + if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), + nonce_len, in, sizeof(kPlaintext), nullptr, 0) || + EVP_AEAD_CTX_seal(ctx.get(), out2, &out_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), + nonce_len, in, sizeof(kPlaintext), nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_seal unexpectedly succeeded.\n"); + return false; + } + ERR_clear_error(); + + memcpy(in, valid_encryption.data(), valid_encryption_len); + if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len, + nonce.data(), nonce_len, in, valid_encryption_len, + nullptr, 0) || + EVP_AEAD_CTX_open(ctx.get(), out2, &out_len, valid_encryption_len, + nonce.data(), nonce_len, in, valid_encryption_len, + nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_open unexpectedly succeeded.\n"); + return false; + } + ERR_clear_error(); + + // Test with out == in, which we expect to work. + memcpy(in, kPlaintext, sizeof(kPlaintext)); + + if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), + nonce_len, in, sizeof(kPlaintext), nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_seal failed in-place.\n"); + return false; + } + + if (out_len != valid_encryption_len || + memcmp(in, valid_encryption.data(), out_len) != 0) { + fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n"); + return false; + } + + memcpy(in, valid_encryption.data(), valid_encryption_len); + if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len, + nonce.data(), nonce_len, in, valid_encryption_len, + nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_open failed in-place.\n"); + return false; + } + + if (out_len != sizeof(kPlaintext) || + memcmp(in, kPlaintext, out_len) != 0) { + fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n"); + return false; + } + + return true; +} + +struct KnownAEAD { + const char name[40]; + const EVP_AEAD *(*func)(void); + // limited_implementation indicates that tests that assume a generic AEAD + // interface should not be performed. For example, the key-wrap AEADs only + // handle inputs that are a multiple of eight bytes in length and the + // SSLv3/TLS AEADs have the concept of “directionâ€. + bool limited_implementation; +}; + +static const struct KnownAEAD kAEADs[] = { + { "aes-128-gcm", EVP_aead_aes_128_gcm, false }, + { "aes-256-gcm", EVP_aead_aes_256_gcm, false }, + { "chacha20-poly1305", EVP_aead_chacha20_poly1305, false }, + { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false }, + { "rc4-md5-tls", EVP_aead_rc4_md5_tls, true }, + { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls, true }, + { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true }, + { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true }, + { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true }, + { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true }, + { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true }, + { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true }, + { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true }, + { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true }, + { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true }, + { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3, true }, + { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3, true }, + { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true }, + { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true }, + { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true }, + { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap, true }, + { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap, true }, + { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false }, + { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false }, + { "", NULL, false }, +}; + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 3) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + const struct KnownAEAD *known_aead; + for (unsigned i = 0;; i++) { + known_aead = &kAEADs[i]; + if (known_aead->func == NULL) { + fprintf(stderr, "Unknown AEAD: %s\n", argv[1]); + return 2; + } + if (strcmp(known_aead->name, argv[1]) == 0) { + break; + } + } + + const EVP_AEAD *const aead = known_aead->func(); + + if (!TestCleanupAfterInitFailure(aead)) { + return 1; + } + + if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) { + fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name); + return 1; + } + + return FileTestMain(TestAEAD, const_cast(aead), argv[2]); +} diff --git a/external/boringssl/crypto/cipher/cipher.c b/external/boringssl/crypto/cipher/cipher.c new file mode 100644 index 0000000000..f61c59f4fe --- /dev/null +++ b/external/boringssl/crypto/cipher/cipher.c @@ -0,0 +1,652 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +#include "internal.h" + + +const EVP_CIPHER *EVP_get_cipherbynid(int nid) { + switch (nid) { + case NID_rc2_cbc: + return EVP_rc2_cbc(); + case NID_rc2_40_cbc: + return EVP_rc2_40_cbc(); + 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_192_cbc: + return EVP_aes_192_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) { + if (c->cipher->cleanup) { + c->cipher->cleanup(c); + } + 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, 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, 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) { + ctx->cipher = NULL; + OPENSSL_PUT_ERROR(CIPHER, 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)) { + ctx->cipher = NULL; + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INITIALIZATION_ERROR); + return 0; + } + } + } else if (!ctx->cipher) { + OPENSSL_PUT_ERROR(CIPHER, 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: + 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: + case EVP_CIPH_OFB_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 (bl - i > in_len) { + 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, 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, 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, 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, CIPHER_R_BAD_DECRYPT); + return 0; + } + + for (i = 0; i < n; i++) { + if (ctx->final[--b] != n) { + OPENSSL_PUT_ERROR(CIPHER, 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, CIPHER_R_NO_CIPHER_SET); + return 0; + } + + if (!ctx->cipher->ctrl) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_NOT_IMPLEMENTED); + return 0; + } + + ret = ctx->cipher->ctrl(ctx, command, arg, ptr); + if (ret == -1) { + OPENSSL_PUT_ERROR(CIPHER, 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, 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; } + +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, "des-ede3-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/external/boringssl/crypto/cipher/cipher_test.cc b/external/boringssl/crypto/cipher/cipher_test.cc new file mode 100644 index 0000000000..fa384c69ea --- /dev/null +++ b/external/boringssl/crypto/cipher/cipher_test.cc @@ -0,0 +1,296 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2015 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +static const EVP_CIPHER *GetCipher(const std::string &name) { + if (name == "DES-CBC") { + return EVP_des_cbc(); + } else if (name == "DES-ECB") { + return EVP_des_ecb(); + } else if (name == "DES-EDE") { + return EVP_des_ede(); + } else if (name == "DES-EDE-CBC") { + return EVP_des_ede_cbc(); + } else if (name == "DES-EDE3-CBC") { + return EVP_des_ede3_cbc(); + } else if (name == "RC4") { + return EVP_rc4(); + } else if (name == "AES-128-ECB") { + return EVP_aes_128_ecb(); + } else if (name == "AES-256-ECB") { + return EVP_aes_256_ecb(); + } else if (name == "AES-128-CBC") { + return EVP_aes_128_cbc(); + } else if (name == "AES-128-GCM") { + return EVP_aes_128_gcm(); + } else if (name == "AES-128-OFB") { + return EVP_aes_128_ofb(); + } else if (name == "AES-192-CBC") { + return EVP_aes_192_cbc(); + } else if (name == "AES-192-ECB") { + return EVP_aes_192_ecb(); + } else if (name == "AES-256-CBC") { + return EVP_aes_256_cbc(); + } else if (name == "AES-128-CTR") { + return EVP_aes_128_ctr(); + } else if (name == "AES-256-CTR") { + return EVP_aes_256_ctr(); + } else if (name == "AES-256-GCM") { + return EVP_aes_256_gcm(); + } else if (name == "AES-256-OFB") { + return EVP_aes_256_ofb(); + } + return nullptr; +} + +static bool TestOperation(FileTest *t, + const EVP_CIPHER *cipher, + bool encrypt, + size_t chunk_size, + const std::vector &key, + const std::vector &iv, + const std::vector &plaintext, + const std::vector &ciphertext, + const std::vector &aad, + const std::vector &tag) { + const std::vector *in, *out; + if (encrypt) { + in = &plaintext; + out = &ciphertext; + } else { + in = &ciphertext; + out = &plaintext; + } + + bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE; + + ScopedEVP_CIPHER_CTX ctx; + if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr, + encrypt ? 1 : 0)) { + return false; + } + if (t->HasAttribute("IV")) { + if (is_aead) { + if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, + iv.size(), 0)) { + return false; + } + } else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) { + t->PrintLine("Bad IV length."); + return false; + } + } + if (is_aead && !encrypt && + !EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(), + const_cast(tag.data()))) { + return false; + } + // The ciphers are run with no padding. For each of the ciphers we test, the + // output size matches the input size. + std::vector result(in->size()); + if (in->size() != out->size()) { + t->PrintLine("Input/output size mismatch (%u vs %u).", (unsigned)in->size(), + (unsigned)out->size()); + return false; + } + // Note: the deprecated |EVP_CIPHER|-based AES-GCM API is sensitive to whether + // parameters are NULL, so it is important to skip the |in| and |aad| + // |EVP_CipherUpdate| calls when empty. + int unused, result_len1 = 0, result_len2; + if (!EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()) || + !EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data(), + -1) || + (!aad.empty() && + !EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(), + aad.size())) || + !EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) { + t->PrintLine("Operation failed."); + return false; + } + if (chunk_size != 0) { + for (size_t i = 0; i < in->size();) { + size_t todo = chunk_size; + if (i + todo > in->size()) { + todo = in->size() - i; + } + + int len; + if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len, + in->data() + i, todo)) { + t->PrintLine("Operation failed."); + return false; + } + result_len1 += len; + i += todo; + } + } else if (!in->empty() && + !EVP_CipherUpdate(ctx.get(), result.data(), &result_len1, + in->data(), in->size())) { + t->PrintLine("Operation failed."); + return false; + } + if (!EVP_CipherFinal_ex(ctx.get(), result.data() + result_len1, + &result_len2)) { + t->PrintLine("Operation failed."); + return false; + } + result.resize(result_len1 + result_len2); + if (!t->ExpectBytesEqual(out->data(), out->size(), result.data(), + result.size())) { + return false; + } + if (encrypt && is_aead) { + uint8_t rtag[16]; + if (tag.size() > sizeof(rtag)) { + t->PrintLine("Bad tag length."); + return false; + } + if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, tag.size(), + rtag) || + !t->ExpectBytesEqual(tag.data(), tag.size(), rtag, + tag.size())) { + return false; + } + } + return true; +} + +static bool TestCipher(FileTest *t, void *arg) { + std::string cipher_str; + if (!t->GetAttribute(&cipher_str, "Cipher")) { + return false; + } + const EVP_CIPHER *cipher = GetCipher(cipher_str); + if (cipher == nullptr) { + t->PrintLine("Unknown cipher: '%s'.", cipher_str.c_str()); + return false; + } + + std::vector key, iv, plaintext, ciphertext, aad, tag; + if (!t->GetBytes(&key, "Key") || + !t->GetBytes(&plaintext, "Plaintext") || + !t->GetBytes(&ciphertext, "Ciphertext")) { + return false; + } + if (EVP_CIPHER_iv_length(cipher) > 0 && + !t->GetBytes(&iv, "IV")) { + return false; + } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) { + if (!t->GetBytes(&aad, "AAD") || + !t->GetBytes(&tag, "Tag")) { + return false; + } + } + + enum { + kEncrypt, + kDecrypt, + kBoth, + } operation = kBoth; + if (t->HasAttribute("Operation")) { + const std::string &str = t->GetAttributeOrDie("Operation"); + if (str == "ENCRYPT") { + operation = kEncrypt; + } else if (str == "DECRYPT") { + operation = kDecrypt; + } else { + t->PrintLine("Unknown operation: '%s'.", str.c_str()); + return false; + } + } + + const std::vector chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16, + 17, 31, 32, 33, 63, 64, 65, 512}; + + for (size_t chunk_size : chunk_sizes) { + // By default, both directions are run, unless overridden by the operation. + if (operation != kDecrypt && + !TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv, + plaintext, ciphertext, aad, tag)) { + return false; + } + + if (operation != kEncrypt && + !TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv, + plaintext, ciphertext, aad, tag)) { + return false; + } + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestCipher, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/cipher/derive_key.c b/external/boringssl/crypto/cipher/derive_key.c new file mode 100644 index 0000000000..9e1634ab96 --- /dev/null +++ b/external/boringssl/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 + +#include + +#include +#include + +#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/external/boringssl/crypto/cipher/e_aes.c b/external/boringssl/crypto/cipher/e_aes.c new file mode 100644 index 0000000000..24c4d8a3ba --- /dev/null +++ b/external/boringssl/crypto/cipher/e_aes.c @@ -0,0 +1,1715 @@ +/* ==================================================================== + * Copyright (c) 2001-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" +#include "../modes/internal.h" + +#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) +#include +#endif + + +OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) /* Unreachable code. */ + +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 +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)) + +#if defined(OPENSSL_ARM) && __ARM_MAX_ARCH__ >= 7 +#define BSAES +static char bsaes_capable(void) { + return CRYPTO_is_NEON_capable(); +} +#endif + +#define HWAES +static int hwaes_capable(void) { + return CRYPTO_is_ARMv8_AES_capable(); +} + +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. */ +static 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(); +} + +static 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. */ +static int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, + AES_KEY *key) { + abort(); +} +static int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, + AES_KEY *key) { + abort(); +} +static void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} +static void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} +static 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. */ +static int hwaes_capable(void) { + return 0; +} + +static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits, + AES_KEY *key) { + abort(); +} + +static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits, + AES_KEY *key) { + abort(); +} + +static void aes_v8_encrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key) { + abort(); +} + +static void aes_v8_decrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key) { + abort(); +} + +static 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(); +} + +static 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); + +#else + +/* On other platforms, aesni_capable() will always return false and so the + * following will never be called. */ +static void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} +static int aesni_set_encrypt_key(const uint8_t *userKey, int bits, + AES_KEY *key) { + abort(); +} +static 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, CIPHER_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *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, uint8_t *out, const uint8_t *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, uint8_t *out, const uint8_t *in, + size_t len) { + 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, + &ctx->num, dat->stream.ctr); + } else { + CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num, + dat->block); + } + return 1; +} + +static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t len) { + EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + + CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num, dat->block); + return 1; +} + +static char aesni_capable(void); + +static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, + block128_f *out_block, const uint8_t *key, + size_t key_len) { + if (aesni_capable()) { + aesni_set_encrypt_key(key, key_len * 8, aes_key); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt); + } + if (out_block) { + *out_block = (block128_f) aesni_encrypt; + } + return (ctr128_f)aesni_ctr32_encrypt_blocks; + } + + if (hwaes_capable()) { + aes_v8_set_encrypt_key(key, key_len * 8, aes_key); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_v8_encrypt); + } + if (out_block) { + *out_block = (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); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); + } + if (out_block) { + *out_block = (block128_f) AES_encrypt; + } + return (ctr128_f)bsaes_ctr32_encrypt_blocks; + } + + if (vpaes_capable()) { + vpaes_set_encrypt_key(key, key_len * 8, aes_key); + if (out_block) { + *out_block = (block128_f) vpaes_encrypt; + } + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt); + } + return NULL; + } + + AES_set_encrypt_key(key, key_len * 8, aes_key); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); + } + if (out_block) { + *out_block = (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_ctr_set_key(&gctx->ks.ks, &gctx->gcm, NULL, 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, &gctx->ks.ks, 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, &gctx->ks.ks, iv, gctx->ivlen); + } else { + memcpy(gctx->iv, iv, gctx->ivlen); + } + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +static void 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); + } +} + +/* 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->ks.ks, 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->ks.ks, 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->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) { + if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len, + gctx->ctr)) { + return -1; + } + } else { + if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) { + return -1; + } + } + } else { + if (gctx->ctr) { + if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len, + gctx->ctr)) { + return -1; + } + } else { + if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) { + return -1; + } + } + } + return len; + } else { + if (!ctx->encrypt) { + if (gctx->taglen < 0 || + !CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen)) { + 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_ofb = { + NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aes_init_key, aes_ofb_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_192_cbc = { + NID_aes_192_cbc, 16 /* block_size */, 24 /* 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_192_ctr = { + NID_aes_192_ctr, 1 /* block_size */, 24 /* 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_192_ecb = { + NID_aes_192_ecb, 16 /* block_size */, 24 /* 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_192_gcm = { + NID_aes_192_gcm, 1 /* block_size */, 24 /* 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_256_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_256_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_256_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_ofb = { + NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aes_init_key, aes_ofb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_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_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, 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, &gctx->ks.ks, 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, &gctx->ks.ks, 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_ofb = { + NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aesni_init_key, aes_ofb_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_192_cbc = { + NID_aes_192_cbc, 16 /* block_size */, 24 /* 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_192_ctr = { + NID_aes_192_ctr, 1 /* block_size */, 24 /* 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_192_ecb = { + NID_aes_192_ecb, 16 /* block_size */, 24 /* 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_192_gcm = { + NID_aes_192_gcm, 1 /* block_size */, 24 /* 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_256_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_256_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_256_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_ofb = { + NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aesni_init_key, aes_ofb_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, ofb) +EVP_CIPHER_FUNCTION(128, gcm) + +EVP_CIPHER_FUNCTION(192, cbc) +EVP_CIPHER_FUNCTION(192, ctr) +EVP_CIPHER_FUNCTION(192, ecb) +EVP_CIPHER_FUNCTION(192, gcm) + +EVP_CIPHER_FUNCTION(256, cbc) +EVP_CIPHER_FUNCTION(256, ctr) +EVP_CIPHER_FUNCTION(256, ecb) +EVP_CIPHER_FUNCTION(256, ofb) +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, 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, CIPHER_R_TAG_TOO_LARGE); + return 0; + } + + gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx)); + if (gcm_ctx == NULL) { + return 0; + } + + gcm_ctx->ctr = + aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, NULL, 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) { + 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, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + gcm_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + const AES_KEY *key = &gcm_ctx->ks.ks; + + memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm)); + CRYPTO_gcm128_setiv(&gcm, key, 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, key, in, out, in_len, + gcm_ctx->ctr)) { + return 0; + } + } else { + if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) { + 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) { + 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, CIPHER_R_BAD_DECRYPT); + return 0; + } + + plaintext_len = in_len - gcm_ctx->tag_len; + + if (max_out_len < plaintext_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + const AES_KEY *key = &gcm_ctx->ks.ks; + + memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm)); + CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len); + + if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) { + return 0; + } + + if (gcm_ctx->ctr) { + if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out, + in_len - gcm_ctx->tag_len, gcm_ctx->ctr)) { + return 0; + } + } else { + if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out, in_len - 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, 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, + NULL, /* init_with_direction */ + aead_aes_gcm_cleanup, + aead_aes_gcm_seal, + aead_aes_gcm_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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, + NULL, /* init_with_direction */ + aead_aes_gcm_cleanup, + aead_aes_gcm_seal, + aead_aes_gcm_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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, 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, 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, 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, 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, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + if (in_len % 8 != 0) { + OPENSSL_PUT_ERROR(CIPHER, 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, CIPHER_R_TOO_LARGE); + return 0; + } + + n = in_len / 8; + + if (n < 2) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE); + return 0; + } + + if (in_len + 8 < in_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + 8) { + OPENSSL_PUT_ERROR(CIPHER, 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, 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, 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, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + if (in_len % 8 != 0) { + OPENSSL_PUT_ERROR(CIPHER, 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, CIPHER_R_TOO_LARGE); + return 0; + } + + if (in_len < 24) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + n = (in_len / 8) - 1; + + if (max_out_len < in_len - 8) { + OPENSSL_PUT_ERROR(CIPHER, 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, 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, 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, + NULL, /* init_with_direction */ + aead_aes_key_wrap_cleanup, + aead_aes_key_wrap_seal, + aead_aes_key_wrap_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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, + NULL, /* init_with_direction */ + aead_aes_key_wrap_cleanup, + aead_aes_key_wrap_seal, + aead_aes_key_wrap_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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; } + + +#define EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN SHA256_DIGEST_LENGTH +#define EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN 12 + +struct aead_aes_ctr_hmac_sha256_ctx { + union { + double align; + AES_KEY ks; + } ks; + ctr128_f ctr; + block128_f block; + SHA256_CTX inner_init_state; + SHA256_CTX outer_init_state; + uint8_t tag_len; +}; + +static void hmac_init(SHA256_CTX *out_inner, SHA256_CTX *out_outer, + const uint8_t hmac_key[32]) { + static const size_t hmac_key_len = 32; + uint8_t block[SHA256_CBLOCK]; + memcpy(block, hmac_key, hmac_key_len); + memset(block + hmac_key_len, 0x36, sizeof(block) - hmac_key_len); + + unsigned i; + for (i = 0; i < hmac_key_len; i++) { + block[i] ^= 0x36; + } + + SHA256_Init(out_inner); + SHA256_Update(out_inner, block, sizeof(block)); + + memset(block + hmac_key_len, 0x5c, sizeof(block) - hmac_key_len); + for (i = 0; i < hmac_key_len; i++) { + block[i] ^= (0x36 ^ 0x5c); + } + + SHA256_Init(out_outer); + SHA256_Update(out_outer, block, sizeof(block)); +} + +static int aead_aes_ctr_hmac_sha256_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len) { + struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx; + static const size_t hmac_key_len = 32; + + if (key_len < hmac_key_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; /* EVP_AEAD_CTX_init should catch this. */ + } + + const size_t aes_key_len = key_len - hmac_key_len; + if (aes_key_len != 16 && aes_key_len != 32) { + OPENSSL_PUT_ERROR(CIPHER, 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_CTR_HMAC_SHA256_TAG_LEN; + } + + if (tag_len > EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE); + return 0; + } + + aes_ctx = OPENSSL_malloc(sizeof(struct aead_aes_ctr_hmac_sha256_ctx)); + if (aes_ctx == NULL) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + + aes_ctx->ctr = + aes_ctr_set_key(&aes_ctx->ks.ks, NULL, &aes_ctx->block, key, aes_key_len); + aes_ctx->tag_len = tag_len; + hmac_init(&aes_ctx->inner_init_state, &aes_ctx->outer_init_state, + key + aes_key_len); + + ctx->aead_state = aes_ctx; + + return 1; +} + +static void aead_aes_ctr_hmac_sha256_cleanup(EVP_AEAD_CTX *ctx) { + struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state; + OPENSSL_cleanse(aes_ctx, sizeof(struct aead_aes_ctr_hmac_sha256_ctx)); + OPENSSL_free(aes_ctx); +} + +static void hmac_update_uint64(SHA256_CTX *sha256, uint64_t value) { + unsigned i; + uint8_t bytes[8]; + + for (i = 0; i < sizeof(bytes); i++) { + bytes[i] = value & 0xff; + value >>= 8; + } + SHA256_Update(sha256, bytes, sizeof(bytes)); +} + +static void hmac_calculate(uint8_t out[SHA256_DIGEST_LENGTH], + const SHA256_CTX *inner_init_state, + const SHA256_CTX *outer_init_state, + const uint8_t *ad, size_t ad_len, + const uint8_t *nonce, const uint8_t *ciphertext, + size_t ciphertext_len) { + SHA256_CTX sha256; + memcpy(&sha256, inner_init_state, sizeof(sha256)); + hmac_update_uint64(&sha256, ad_len); + hmac_update_uint64(&sha256, ciphertext_len); + SHA256_Update(&sha256, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN); + SHA256_Update(&sha256, ad, ad_len); + + /* Pad with zeros to the end of the SHA-256 block. */ + const unsigned num_padding = + (SHA256_CBLOCK - ((sizeof(uint64_t)*2 + + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN + ad_len) % + SHA256_CBLOCK)) % + SHA256_CBLOCK; + uint8_t padding[SHA256_CBLOCK]; + memset(padding, 0, num_padding); + SHA256_Update(&sha256, padding, num_padding); + + SHA256_Update(&sha256, ciphertext, ciphertext_len); + + uint8_t inner_digest[SHA256_DIGEST_LENGTH]; + SHA256_Final(inner_digest, &sha256); + + memcpy(&sha256, outer_init_state, sizeof(sha256)); + SHA256_Update(&sha256, inner_digest, sizeof(inner_digest)); + SHA256_Final(out, &sha256); +} + +static void aead_aes_ctr_hmac_sha256_crypt( + const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx, uint8_t *out, + const uint8_t *in, size_t len, const uint8_t *nonce) { + /* Since the AEAD operation is one-shot, keeping a buffer of unused keystream + * bytes is pointless. However, |CRYPTO_ctr128_encrypt| requires it. */ + uint8_t partial_block_buffer[AES_BLOCK_SIZE]; + unsigned partial_block_offset = 0; + memset(partial_block_buffer, 0, sizeof(partial_block_buffer)); + + uint8_t counter[AES_BLOCK_SIZE]; + memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN); + memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4); + + if (aes_ctx->ctr) { + CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter, + partial_block_buffer, &partial_block_offset, + aes_ctx->ctr); + } else { + CRYPTO_ctr128_encrypt(in, out, len, &aes_ctx->ks.ks, counter, + partial_block_buffer, &partial_block_offset, + aes_ctx->block); + } +} + +static int aead_aes_ctr_hmac_sha256_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_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state; + const uint64_t in_len_64 = in_len; + + if (in_len + aes_ctx->tag_len < in_len || + /* This input is so large it would overflow the 32-bit block counter. */ + in_len_64 >= (UINT64_C(1) << 32) * AES_BLOCK_SIZE) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + aes_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, in_len, nonce); + + uint8_t hmac_result[SHA256_DIGEST_LENGTH]; + hmac_calculate(hmac_result, &aes_ctx->inner_init_state, + &aes_ctx->outer_init_state, ad, ad_len, nonce, out, in_len); + memcpy(out + in_len, hmac_result, aes_ctx->tag_len); + *out_len = in_len + aes_ctx->tag_len; + + return 1; +} + +static int aead_aes_ctr_hmac_sha256_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_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state; + size_t plaintext_len; + + if (in_len < aes_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + plaintext_len = in_len - aes_ctx->tag_len; + + if (max_out_len < plaintext_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + uint8_t hmac_result[SHA256_DIGEST_LENGTH]; + hmac_calculate(hmac_result, &aes_ctx->inner_init_state, + &aes_ctx->outer_init_state, ad, ad_len, nonce, in, + plaintext_len); + if (CRYPTO_memcmp(hmac_result, in + plaintext_len, aes_ctx->tag_len) != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, plaintext_len, nonce); + + *out_len = plaintext_len; + return 1; +} + +static const EVP_AEAD aead_aes_128_ctr_hmac_sha256 = { + 16 /* AES key */ + 32 /* HMAC key */, + 12, /* nonce length */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */ + + aead_aes_ctr_hmac_sha256_init, + NULL /* init_with_direction */, + aead_aes_ctr_hmac_sha256_cleanup, + aead_aes_ctr_hmac_sha256_seal, + aead_aes_ctr_hmac_sha256_open, + NULL /* get_rc4_state */, + NULL /* get_iv */, +}; + +static const EVP_AEAD aead_aes_256_ctr_hmac_sha256 = { + 32 /* AES key */ + 32 /* HMAC key */, + 12, /* nonce length */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */ + + aead_aes_ctr_hmac_sha256_init, + NULL /* init_with_direction */, + aead_aes_ctr_hmac_sha256_cleanup, + aead_aes_ctr_hmac_sha256_seal, + aead_aes_ctr_hmac_sha256_open, + NULL /* get_rc4_state */, + NULL /* get_iv */, +}; + +const EVP_AEAD *EVP_aead_aes_128_ctr_hmac_sha256(void) { + return &aead_aes_128_ctr_hmac_sha256; +} + +const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void) { + return &aead_aes_256_ctr_hmac_sha256; +} + +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() && CRYPTO_is_ARMv8_PMULL_capable(); +#else + return 0; +#endif +} diff --git a/external/boringssl/crypto/cipher/e_chacha20poly1305.c b/external/boringssl/crypto/cipher/e_chacha20poly1305.c new file mode 100644 index 0000000000..852b2c64ee --- /dev/null +++ b/external/boringssl/crypto/cipher/e_chacha20poly1305.c @@ -0,0 +1,302 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +#define POLY1305_TAG_LEN 16 + +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, 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_length(poly1305_state *poly1305, size_t data_len) { + uint8_t length_bytes[8]; + unsigned i; + + for (i = 0; i < sizeof(length_bytes); i++) { + length_bytes[i] = data_len; + data_len >>= 8; + } + + CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); +} + +typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len); + +/* aead_poly1305 fills |tag| with the authentication tag for the given + * inputs, using |update| to control the order and format that the inputs are + * signed/authenticated. */ +static void aead_poly1305(aead_poly1305_update update, + uint8_t tag[POLY1305_TAG_LEN], + const struct aead_chacha20_poly1305_ctx *c20_ctx, + const uint8_t nonce[12], const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len) { + alignas(16) uint8_t poly1305_key[32]; + memset(poly1305_key, 0, sizeof(poly1305_key)); + CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), + c20_ctx->key, nonce, 0); + poly1305_state ctx; + CRYPTO_poly1305_init(&ctx, poly1305_key); + update(&ctx, ad, ad_len, ciphertext, ciphertext_len); + CRYPTO_poly1305_finish(&ctx, tag); +} + +static int seal_impl(aead_poly1305_update poly1305_update, + const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t nonce[12], + 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; + const uint64_t in_len_64 = in_len; + + /* |CRYPTO_chacha_20| uses a 32-bit block counter. 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 >= (UINT64_C(1) << 32) * 64 - 64) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (in_len + c20_ctx->tag_len < in_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + c20_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); + + alignas(16) uint8_t tag[POLY1305_TAG_LEN]; + aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len); + + memcpy(out + in_len, tag, c20_ctx->tag_len); + *out_len = in_len + c20_ctx->tag_len; + return 1; +} + +static int open_impl(aead_poly1305_update poly1305_update, + const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t nonce[12], + 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; + size_t plaintext_len; + const uint64_t in_len_64 = in_len; + + if (in_len < c20_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + /* |CRYPTO_chacha_20| uses a 32-bit block counter. 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 >= (UINT64_C(1) << 32) * 64 - 64) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + plaintext_len = in_len - c20_ctx->tag_len; + alignas(16) uint8_t tag[POLY1305_TAG_LEN]; + aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in, + plaintext_len); + if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) { + OPENSSL_PUT_ERROR(CIPHER, 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 void poly1305_update_padded_16(poly1305_state *poly1305, + const uint8_t *data, size_t data_len) { + static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */ + + CRYPTO_poly1305_update(poly1305, data, data_len); + if (data_len % 16 != 0) { + CRYPTO_poly1305_update(poly1305, padding, sizeof(padding) - (data_len % 16)); + } +} + +static void poly1305_update(poly1305_state *ctx, const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len) { + poly1305_update_padded_16(ctx, ad, ad_len); + poly1305_update_padded_16(ctx, ciphertext, ciphertext_len); + poly1305_update_length(ctx, ad_len); + poly1305_update_length(ctx, ciphertext_len); +} + +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) { + if (nonce_len != 12) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + return seal_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in, + in_len, ad, ad_len); +} + +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) { + if (nonce_len != 12) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + return open_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in, + in_len, ad, ad_len); +} + +static const EVP_AEAD aead_chacha20_poly1305 = { + 32, /* key len */ + 12, /* nonce len */ + POLY1305_TAG_LEN, /* overhead */ + POLY1305_TAG_LEN, /* max tag length */ + aead_chacha20_poly1305_init, + NULL, /* init_with_direction */ + aead_chacha20_poly1305_cleanup, + aead_chacha20_poly1305_seal, + aead_chacha20_poly1305_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_chacha20_poly1305(void) { + return &aead_chacha20_poly1305; +} + +static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len) { + CRYPTO_poly1305_update(ctx, ad, ad_len); + poly1305_update_length(ctx, ad_len); + CRYPTO_poly1305_update(ctx, ciphertext, ciphertext_len); + poly1305_update_length(ctx, ciphertext_len); +} + +static int aead_chacha20_poly1305_old_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) { + if (nonce_len != 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + uint8_t nonce_96[12]; + memset(nonce_96, 0, 4); + memcpy(nonce_96 + 4, nonce, 8); + return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len, + nonce_96, in, in_len, ad, ad_len); +} + +static int aead_chacha20_poly1305_old_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 (nonce_len != 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + uint8_t nonce_96[12]; + memset(nonce_96, 0, 4); + memcpy(nonce_96 + 4, nonce, 8); + return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len, + nonce_96, in, in_len, ad, ad_len); +} + +static const EVP_AEAD aead_chacha20_poly1305_old = { + 32, /* key len */ + 8, /* nonce len */ + POLY1305_TAG_LEN, /* overhead */ + POLY1305_TAG_LEN, /* max tag length */ + aead_chacha20_poly1305_init, + NULL, /* init_with_direction */ + aead_chacha20_poly1305_cleanup, + aead_chacha20_poly1305_old_seal, + aead_chacha20_poly1305_old_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) { + return &aead_chacha20_poly1305_old; +} diff --git a/external/boringssl/crypto/cipher/e_des.c b/external/boringssl/crypto/cipher/e_des.c new file mode 100644 index 0000000000..2ba2bed38b --- /dev/null +++ b/external/boringssl/crypto/cipher/e_des.c @@ -0,0 +1,207 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include + +#include "internal.h" + + +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; + + DES_ncbc_encrypt(in, out, 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; } + + +static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t in_len) { + if (in_len < ctx->cipher->block_size) { + return 1; + } + in_len -= ctx->cipher->block_size; + + EVP_DES_KEY *dat = (EVP_DES_KEY *) ctx->cipher_data; + size_t i; + for (i = 0; i <= in_len; i += ctx->cipher->block_size) { + DES_ecb_encrypt((DES_cblock *) (in + i), (DES_cblock *) (out + i), + &dat->ks.ks, ctx->encrypt); + } + return 1; +} + +static const EVP_CIPHER des_ecb = { + NID_des_ecb, 8 /* block_size */, 8 /* key_size */, + 0 /* iv_len */, sizeof(EVP_DES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, des_init_key, des_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_ecb(void) { return &des_ecb; } + + +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; + + 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 des_ede3_cbc = { + NID_des_ede3_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 &des_ede3_cbc; } + + +static int des_ede_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[0], &dat->ks.ks[2]); + + return 1; +} + +static const EVP_CIPHER des_ede_cbc = { + NID_des_ede_cbc, 8 /* block_size */, 16 /* key_size */, + 8 /* iv_len */, sizeof(DES_EDE_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, des_ede_init_key , des_ede3_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_ede_cbc(void) { return &des_ede_cbc; } + + +static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t in_len) { + if (in_len < ctx->cipher->block_size) { + return 1; + } + in_len -= ctx->cipher->block_size; + + DES_EDE_KEY *dat = (DES_EDE_KEY *) ctx->cipher_data; + size_t i; + for (i = 0; i <= in_len; i += ctx->cipher->block_size) { + DES_ecb3_encrypt((DES_cblock *) (in + i), (DES_cblock *) (out + i), + &dat->ks.ks[0], &dat->ks.ks[1], &dat->ks.ks[2], + ctx->encrypt); + } + return 1; +} + +static const EVP_CIPHER des_ede_ecb = { + NID_des_ede_cbc, 8 /* block_size */, 16 /* key_size */, + 0 /* iv_len */, sizeof(DES_EDE_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, des_ede_init_key , des_ede_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_ede(void) { return &des_ede_ecb; } diff --git a/external/boringssl/crypto/cipher/e_null.c b/external/boringssl/crypto/cipher/e_null.c new file mode 100644 index 0000000000..3d6a24c38a --- /dev/null +++ b/external/boringssl/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 + +#include + +#include + +#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/external/boringssl/crypto/cipher/e_rc2.c b/external/boringssl/crypto/cipher/e_rc2.c new file mode 100644 index 0000000000..67418d5497 --- /dev/null +++ b/external/boringssl/crypto/cipher/e_rc2.c @@ -0,0 +1,443 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include "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; + case EVP_CTRL_SET_RC2_KEY_BITS: + /* Should be overridden by later call to |EVP_CTRL_INIT|, but + * people call it, so it may as well work. */ + key->key_bits = arg; + return 1; + + default: + return -1; + } +} + +static const EVP_CIPHER rc2_40_cbc = { + 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; +} + +static const EVP_CIPHER rc2_cbc = { + NID_rc2_cbc, + 8 /* block size */, + 16 /* 128 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_cbc(void) { + return &rc2_cbc; +} diff --git a/external/boringssl/crypto/cipher/e_rc4.c b/external/boringssl/crypto/cipher/e_rc4.c new file mode 100644 index 0000000000..e7c2ccaffd --- /dev/null +++ b/external/boringssl/crypto/cipher/e_rc4.c @@ -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.] */ + +#include +#include + +#include +#include +#include + + +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; } diff --git a/external/boringssl/crypto/cipher/e_ssl3.c b/external/boringssl/crypto/cipher/e_ssl3.c new file mode 100644 index 0000000000..7dddf242f7 --- /dev/null +++ b/external/boringssl/crypto/cipher/e_ssl3.c @@ -0,0 +1,463 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +typedef struct { + EVP_CIPHER_CTX cipher_ctx; + EVP_MD_CTX md_ctx; +} 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_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, enum evp_aead_direction_t dir, + 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, CIPHER_R_UNSUPPORTED_TAG_SIZE); + return 0; + } + + if (key_len != EVP_AEAD_key_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, 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); + assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len); + /* 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, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx); + EVP_MD_CTX_init(&ssl3_ctx->md_ctx); + + ctx->aead_state = ssl3_ctx; + if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len], + &key[mac_key_len + enc_key_len], + dir == evp_aead_seal) || + !EVP_DigestInit_ex(&ssl3_ctx->md_ctx, md, NULL) || + !EVP_DigestUpdate(&ssl3_ctx->md_ctx, key, mac_key_len)) { + aead_ssl3_cleanup(ctx); + ctx->aead_state = NULL; + return 0; + } + EVP_CIPHER_CTX_set_padding(&ssl3_ctx->cipher_ctx, 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 (!ssl3_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 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, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE); + return 0; + } + + if (ad_len != 11 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + 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; + + if (ssl3_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 0; + } + + size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx); + if (in_len < mac_len) { + OPENSSL_PUT_ERROR(CIPHER, 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, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (ad_len != 11 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + return 0; + } + + if (in_len > INT_MAX) { + /* EVP_CIPHER takes int as input. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + 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, 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, 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, CIPHER_R_BAD_DECRYPT); + return 0; + } + + *out_len = data_len; + return 1; +} + +static int aead_ssl3_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) { + AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; + if (EVP_CIPHER_CTX_cipher(&ssl3_ctx->cipher_ctx) != EVP_rc4()) { + return 0; + } + + *out_key = (RC4_KEY*) ssl3_ctx->cipher_ctx.cipher_data; + return 1; +} + +static int aead_ssl3_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_iv_len) { + AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; + const size_t iv_len = EVP_CIPHER_CTX_iv_length(&ssl3_ctx->cipher_ctx); + if (iv_len <= 1) { + return 0; + } + + *out_iv = ssl3_ctx->cipher_ctx.iv; + *out_iv_len = iv_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, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(), + EVP_sha1()); +} + +static int aead_null_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(), + 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 */ + NULL, /* init */ + aead_rc4_md5_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + aead_ssl3_get_rc4_state, + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_rc4_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + aead_ssl3_get_rc4_state, + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_aes_128_cbc_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + aead_ssl3_get_iv, +}; + +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 */ + NULL, /* init */ + aead_aes_256_cbc_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + aead_ssl3_get_iv, +}; + +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 */ + NULL, /* init */ + aead_des_ede3_cbc_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + aead_ssl3_get_iv, +}; + +static const EVP_AEAD aead_null_sha1_ssl3 = { + SHA_DIGEST_LENGTH, /* key len */ + 0, /* nonce len */ + SHA_DIGEST_LENGTH, /* overhead (SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_null_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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; +} + +const EVP_AEAD *EVP_aead_null_sha1_ssl3(void) { return &aead_null_sha1_ssl3; } diff --git a/external/boringssl/crypto/cipher/e_tls.c b/external/boringssl/crypto/cipher/e_tls.c new file mode 100644 index 0000000000..b87b0d6ebf --- /dev/null +++ b/external/boringssl/crypto/cipher/e_tls.c @@ -0,0 +1,673 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + /* implicit_iv is one iff this is a pre-TLS-1.1 CBC cipher without an explicit + * IV. */ + char implicit_iv; +} AEAD_TLS_CTX; + +OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE < 256, mac_key_len_fits_in_uint8_t); + +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_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, enum evp_aead_direction_t dir, + 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, CIPHER_R_UNSUPPORTED_TAG_SIZE); + return 0; + } + + if (key_len != EVP_AEAD_key_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, 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); + assert(mac_key_len + enc_key_len + + (implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len); + /* 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, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx); + HMAC_CTX_init(&tls_ctx->hmac_ctx); + assert(mac_key_len <= EVP_MAX_MD_SIZE); + memcpy(tls_ctx->mac_key, key, mac_key_len); + tls_ctx->mac_key_len = (uint8_t)mac_key_len; + tls_ctx->implicit_iv = implicit_iv; + + ctx->aead_state = tls_ctx; + if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len], + implicit_iv ? &key[mac_key_len + enc_key_len] : NULL, + dir == evp_aead_seal) || + !HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) { + aead_tls_cleanup(ctx); + ctx->aead_state = NULL; + return 0; + } + EVP_CIPHER_CTX_set_padding(&tls_ctx->cipher_ctx, 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 (!tls_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 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, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); + return 0; + } + + if (ad_len != 13 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + 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; + if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || + !HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) || + !HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) || + !HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) || + !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) { + return 0; + } + + /* 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 (tls_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 0; + } + + if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) { + OPENSSL_PUT_ERROR(CIPHER, 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, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); + return 0; + } + + if (ad_len != 13 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + return 0; + } + + if (in_len > INT_MAX) { + /* EVP_CIPHER takes int as input. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + 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, 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, 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); + + unsigned mac_len_u; + if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || + !HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) || + !HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) || + !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) { + return 0; + } + mac_len = mac_len_u; + + 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, CIPHER_R_BAD_DECRYPT); + return 0; + } + + /* End of timing-sensitive code. */ + + *out_len = data_len; + return 1; +} + +static int aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5(), + 0); +} + +static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, 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, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(), + EVP_sha1(), 1); +} + +static int aead_rc4_tls_get_rc4_state(const EVP_AEAD_CTX *ctx, + const RC4_KEY **out_key) { + const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state; + if (EVP_CIPHER_CTX_cipher(&tls_ctx->cipher_ctx) != EVP_rc4()) { + return 0; + } + + *out_key = (const RC4_KEY*) tls_ctx->cipher_ctx.cipher_data; + return 1; +} + +static int aead_tls_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_iv_len) { + const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state; + const size_t iv_len = EVP_CIPHER_CTX_iv_length(&tls_ctx->cipher_ctx); + if (iv_len <= 1) { + return 0; + } + + *out_iv = tls_ctx->cipher_ctx.iv; + *out_iv_len = iv_len; + return 1; +} + +static int aead_null_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(), + EVP_sha1(), 1 /* implicit iv */); +} + +static const EVP_AEAD aead_rc4_md5_tls = { + MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */ + 0, /* nonce len */ + MD5_DIGEST_LENGTH, /* overhead */ + MD5_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_rc4_md5_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + aead_rc4_tls_get_rc4_state, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_rc4_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + aead_rc4_tls_get_rc4_state, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_aes_128_cbc_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_aes_128_cbc_sha1_tls_implicit_iv_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + aead_tls_get_iv, /* get_iv */ +}; + +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) */ + SHA256_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_128_cbc_sha256_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_aes_256_cbc_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_aes_256_cbc_sha1_tls_implicit_iv_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + aead_tls_get_iv, /* get_iv */ +}; + +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) */ + SHA256_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_256_cbc_sha256_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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) */ + SHA384_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_256_cbc_sha384_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_des_ede3_cbc_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +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 */ + NULL, /* init */ + aead_des_ede3_cbc_sha1_tls_implicit_iv_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + aead_tls_get_iv, /* get_iv */ +}; + +static const EVP_AEAD aead_null_sha1_tls = { + SHA_DIGEST_LENGTH, /* key len */ + 0, /* nonce len */ + SHA_DIGEST_LENGTH, /* overhead (SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_null_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; } + +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; +} + +const EVP_AEAD *EVP_aead_null_sha1_tls(void) { return &aead_null_sha1_tls; } diff --git a/external/boringssl/crypto/cipher/internal.h b/external/boringssl/crypto/cipher/internal.h new file mode 100644 index 0000000000..72ac1189f3 --- /dev/null +++ b/external/boringssl/crypto/cipher/internal.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_CIPHER_INTERNAL_H +#define OPENSSL_HEADER_CIPHER_INTERNAL_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* EVP_CIPH_MODE_MASK contains the bits of |flags| that represent the mode. */ +#define EVP_CIPH_MODE_MASK 0x3f + + +/* 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; + + /* init initialises an |EVP_AEAD_CTX|. If this call returns zero then + * |cleanup| will not be called for that context. */ + int (*init)(EVP_AEAD_CTX *, const uint8_t *key, size_t key_len, + size_t tag_len); + int (*init_with_direction)(EVP_AEAD_CTX *, const uint8_t *key, size_t key_len, + size_t tag_len, enum evp_aead_direction_t dir); + void (*cleanup)(EVP_AEAD_CTX *); + + int (*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); + + int (*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); + + int (*get_rc4_state)(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key); + + int (*get_iv)(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_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/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..9ffe136af1 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +5bc08f07c3a6e236a177f67844f1a5012a202ad5 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..722430d14f --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +477f1eb1b47788dad48444b16e5430efe5c0cf2c \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..34d71526de --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +2b34b7bfb374532266b4b70a842e62b98e814de1 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..1350dce9ee --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +c6419fa62598adb03186c2d4199ddc79c6ddda0a \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt b/external/boringssl/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt new file mode 100644 index 0000000000..d4803a0fb2 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt @@ -0,0 +1,336 @@ +KEY: 067b841a2540cb467b75f2188f5da4b5aeb7e0e44582a2b668b5b1ff39e21c4e65745470fb1be1aa909c62fabcf0e6ac +NONCE: 10e0ecb00da5345127407150 +IN: +AD: +CT: +TAG: a82a891565e466957ad5a499d45b579d31acaf582f54d518f8f9c128936dac4c + +KEY: c9d9ef2c808c3f8b22f659c12147104b08cec2390a84f0c4b887ca4c247c8c9dd45e72f48b30b67a8545750387232344 +NONCE: 58bddf96158a3a588bf3ec05 +IN: +AD: 5d +CT: +TAG: 3580c1601d1c9a5b1595d3dee35b0cd9e1b115d8b0abee557b2c207b8d0df5ee + +KEY: f755dc6786e21f39b595389a51d36673e1ffb94ffc066c03873eb31839be6fa319fd31c8bea29f03ff28831861e60b6e +NONCE: bd6c80797f1f4c563b06fd3b +IN: +AD: 78d88005136e312639572343a2d0daf7483d8235291ee3ac002469456b075243dc03380c387030d546c2b1 +CT: +TAG: dede80d810fc449a769c79a5ecd2c0d68e9e0fae567781e623ab2098c88d8a86 + +KEY: 43a0a28fef8b89b8fb0f76de01d802935ad561e27ca9c9fa629347be676a6af758501b6a652f369045da5fef751b56bb +NONCE: 0f6472f1e589c16ca5ad45b2 +IN: +AD: 78e4eafccfc87631f0314c442ba4c07bca36f996a5b3408f9e445d6009a87ded16b33a4af9537a4619cab70d +CT: +TAG: 11fa62dd8374aabe728ebf7e9aa1c02cf8f2dbc29f9aaf1940313f0b7c3e0301 + +KEY: acf8e5f1bd64e6289370650b5b3fd773320025c8b229fd335d9461768cd0a17b4bcc946919932efdc9fc84a7f50768bf +NONCE: 1aecfc90d28bcdcc5a8e3578 +IN: +AD: 6daedbdc69133b56f6a8f098f9f70cdb7e129e51115df385a6d86204a53412cd999cf2e69f45e168efed4742b6 +CT: +TAG: fbe0511ba0ec5709def9966a9b05facf171cddd81ee2cd56e7afc867af465f31 + +KEY: 2773c92e6cddc9a5e5dcaf3893080fd2153f009d807df0b175c76615645f2087539e299d8411b27badb749a9845c5e29 +NONCE: 6d04ed129299651aec0465f8 +IN: +AD: 44219577e361a7a4681172d120a2d653a53ec74bc487ccde4954835943bca413d55c65dc665310148654d8c1e2e6bc2f06ec344473120ad1f95739b993a57f9ec0b3299cc088f385894fff876fc2ce8ce6b77ca253f177ba615101e84e17ad0e60704cff195dcd50eb48c77de409797e0b1c8c4c5b9215a4a0399954a008267b +CT: +TAG: 6ab61ac4493e58e48d071d994a000f1c1f498d22f83c8d2af56b03c155afc57e + +KEY: 23189bf23bc4b734410d1c7ae321c42e144a25347a8029bb925e3d8ac1b92f4eb97227c1dece86ae9dea7d127eb33f9b +NONCE: 30681944cd5d78f46d36ed8a +IN: 59 +AD: +CT: 92 +TAG: 986aa8438da3cf4a98f478f90d24908c6a4e848f299873e649b256f5499d89d9 + +KEY: 463d1148325c5f57af670877068a78203571b8b19f40e9f0373156b7448ab315df86c77d7c85ba6e54b9bc329399f687 +NONCE: cc9d015a4b5a888b36b14d05 +IN: 28 +AD: 6a +CT: 05 +TAG: f66e8dc794b142944fa46d5c04a3e3fe00291668374846d763f2beeffd4ca4a0 + +KEY: 937eaab44e7c7d2cd5bbb053c12e6255e0aaa42cbe7d83025b7a2887eff8f098d019c80af849b0ed7da54a5ba5b39200 +NONCE: 2b160d24df579836e1572ea2 +IN: 9a +AD: 35841a33ba3a6ed3d89a1f76d06c61613d09834847e5a41f8616748e30c14335e5baa43d49fceaf85aeb22 +CT: 80 +TAG: 5e5799c147be0329dbcabf7ecdba6ac595ebc2d06b9d757426fbb31e8b39f62a + +KEY: 68a746f382fcc11c02af7b352b9d710c137a9f59bc5886dc374ca88cdc01b86fe5678fde16cfa846846539f67a429276 +NONCE: b94346c033ac1a3d709c4f09 +IN: ad +AD: ad61c9168debf9974e19759088944e888346aff99f3e2e4522549c8ae332a0f41922972fb7c1d5ff24e7ae4b +CT: 46 +TAG: 62ae92ff64710a9f260da2562e246356e9d749c3584fb9f40d9572307ccbbd31 + +KEY: 6622579d1d6350fd5dff432b69d172cc51f99bdaff50b0a1c0f4cda8d5904581ba8657ba61c6936407243d7fb64b00da +NONCE: a880caa7157a13540d2b724f +IN: 2a +AD: 95a23eafcff892deecaf093109d30290d819851ad5c91061510e54baa2b039b114c815da20f0e3ba2ba4875bdd +CT: ce +TAG: 33f09666f9fd1d92f137d9f3f7092b47b2bd71a7e3139dcd19a803a6b17f2a3a + +KEY: 91ce9dd87c7d11d2c4da41863b6851c40fba786a612e0fbf0d1956a71286dfc61fa10bf7d148cecd72b6ceeb82b68d3f +NONCE: a50dc3d8fd63d3076cc70ff6 +IN: da +AD: 9ce8e1a777c159ec775abbd67d85e84f3550c3296e848dec18b61bbd713a98a033805bfe6e2f2a011dd7fd754708e524168142aeee579cae19c7eab78fa7c42fa335f0c725baf556160beef9e4afd1050a2c8813be6bd14cc6982116d0229d53e9b4de923abf6ba99bdffe1d5f21748ae74caddb077d9f7488b394436222beca +CT: 2b +TAG: 1541cd745bc0259dd72a212474f5c7b8c121dd0289d674e5ba8d56a220d1f1d0 + +KEY: 1ad577d3b47e3fff8528e336a43a7ffef72f811e05b5c69ccfe777b10f29061e289178e394a1c87ba483c7f98ea5431d +NONCE: 1fcaa4757a9e48ed2cb3be62 +IN: 46d30dac550103006c292a9ac05d31 +AD: +CT: 37616eba30c55595fa0ad5d50f91ca +TAG: 5c3ac4010f75adf90f81e775b07ab939e7551a9b8e0486ba33766728ed498245 + +KEY: 6df310dc1847b42c68e50b03d154b73d7f3823354b32759c5369bce1a1b4cd63ccdb911c2dc792acf84b8b8f3fdfb89d +NONCE: 92e6759a31dd556ff9124d73 +IN: 6daba76658db642209e276ff7c8d46 +AD: 32 +CT: ce1814c03037078b6be3252460af48 +TAG: 46e61913f2a1ff6e77faade9a7cd37a82eff3ebec4276fbddff9266b9c9bd873 + +KEY: f848c2300995f5c98dcd0db24574d7c61459ca64c084421c6ad156e80e398904417ee745245ddae91be20fb07e66bdb6 +NONCE: 3b177e11063445717f417d14 +IN: bbf225131c821a6a60817cc65bf699 +AD: 4c5ab4fdbe0018344629349feed5d8c3ae0c5b64f2b093576a2aaa1225e7a50eca01a9962c9b4f8fc5c12a +CT: 1538957e78f3ab0fed77906153d715 +TAG: 2c7760d47407ad7b0d5b85fa4967eaa7b6c0bb6eb16619adde7a191abfdf3da3 + +KEY: d406cac07630ce2c071732a0ec95f55123486d2677465768dc7db13f90902cf172f92e19f57f5cf7c68cd7bde7ee4b4b +NONCE: 766aede0120b634a4be6fa12 +IN: 3804d40090a38d4c97a5fff631068c +AD: 7707b7d0f266284e84c2ecdd5a18832650c3e27d66697616c9e9bb2f8a09a3295de0119582ca3614b9608548 +CT: 91e96462a5dfbe8b7af201158a36dc +TAG: 56623e5813070a0e2f5184aed83b9863301ca02e3108f7afc478d48305e397f8 + +KEY: 42bb22a317ed9f9df8119746e9a1257217e5b0144051ca56f39587021d969bc0acc02795f3bd201031e8c05af08ad079 +NONCE: 0a9f6bace71a1ab21f4917df +IN: 013f7b8c75307158f4f300450e7a78 +AD: cd95a649ae215fe73442a6991e157232cbcabecff6042b87d41557e35b97606d606c3ded54f5d3db7aa2773f67 +CT: e588dbcecbdb7667dccf7fe34f8387 +TAG: b04461748109ed9068c7e9c0446528ef09b01613c3b3aa1ffeed6685ebb550f5 + +KEY: e1cfcbaba3a04b5108ce2a87099a6aae936ee38acd92b7e6b7df0e3bcb9ad18fc579b5d470ef3e04c23459f509852458 +NONCE: 112dd267174bcd81e6fbd924 +IN: 288a1e44b406aebec7b418674f81e7 +AD: 7809d8011c5a963df14fb8981e874119c60b7a9d897d13a05651759db5835deffdd991fbf98b9aa71c79e48bd701b228ba248b6bed874b02da7fcf28a04c38b81c0ff628846015258af30dbf28ea4f3283f664f888fca545f5fc57dccc4ad1dd476c52fba341182ecf783706c5c458bf0ee5ec83454afba78eb8b5ca17af88ec +CT: 80f4e1012d76f6180ca00fd32c8fec +TAG: 6de00bf2fd3c88ab34ca9390f7e559875e43e0f938303816a3a75a35729bc453 + +KEY: 84172547d8608bd9e788a7bb60df2982963716e45f8e63f0c5033327d85c920c5e3776e314246b1694b739c39abfa29f +NONCE: a3f1643bb504b7ce9e5b43c2 +IN: 7e76323eb13e64da9b240a57c95c855b +AD: +CT: 966487c18f025d67b42a04c30d3ff4c3 +TAG: 8bb03d893f0ce8ea4a6a47245bc7f20c72acf8caa466edd01365d0f74c929463 + +KEY: 02dee8f2e63b37fe3cbae9101fed0946e05e5090510bef3324a82e3f27456a45ab1b6cdeddb1fe515ad07aefeee6ccbc +NONCE: 64723d21365d62926d5c2262 +IN: 4f1f132c50a01ad48882ce88655b33f7 +AD: d8 +CT: b102082e14cd9ecc0895f7a6f08ab522 +TAG: 2c09651c1a51cb8a375746236fe258a36e725936ccedbc4dfafee6c3084a4716 + +KEY: 5db57cf6301bab815d38879b35c9db72fd40ac576d259ad5074d0828364050554e9fc08335b5f2bf066b09e50fbe6ba4 +NONCE: 36e5340d844de213c312177a +IN: 41a6e910b14388740ea351eb1df980c9 +AD: 8316a6b9b155b2de5e724f7593ecdcee442eaef7b9ad204eda4744a5e648c2dd84f48ee81397e485953465 +CT: ee21d4d47042415ca27d2ecb11b13d79 +TAG: 5015da5a3339389d39d0fcafb56ef4005b342e69ba47930e84408d33aadf5f2a + +KEY: a493dd6de6fd6584599096442dd9345f6f2d8fc2d426c78eee2b992b4071aba4ce463f3ca293c84b2faf3e8644b6ec25 +NONCE: 4f9be6f788ee960adc650d86 +IN: 4de6e244251091cf13762d20685e9085 +AD: d15da312b7522c18384acdbf6348b5e105557f1790a6a203a65acd73397524681666743f3145048775ad84e3 +CT: bb1296457daa39d889c8f986938d6a39 +TAG: b93548cea90c34d03d6f5683ae2cc78814531b803d42cfe57623fd4bdc8f084c + +KEY: 8cc59ebe2c7375a70915c48d2978a1f720bc0aa2775ce9189ae7b3d5dda9a81e56cde0e0a29939599409b71f0b65f346 +NONCE: b0ab041f37ea1e594f1eddb3 +IN: cd0aeaf6806cb99e6bc1c8c5d830de8c +AD: 8f4b5a9609df757826dbe7e51bb6a2c6f45f601263cf668836193513cf008ab6b36a7d5447039f1268821ec37e +CT: 5d5375b9d9cff6d0c1dbd14221509a0d +TAG: d8850bbc838e068b817c24d018f8f1e1cb8aac0a68392a700f48099f81b6c37c + +KEY: f3e9c507478d3f99dbf3e2421e45929b096ab3f3d4aa4ef9c338c5a1a2425c9936b7df602502d33cbafcf781350da77e +NONCE: d4872a30c9d1fa9001a25afe +IN: 25e05ea69a956b12a9be4ef03ae9d30c +AD: 8b346c20e7c64b805d9c8d325829201753069c60b3f221f31474f55cb20315373ccd7c2a8f215e9efc407ae91b05d8b6d693a3780fdd65d7715cdded86c3d6204055812f3fce897f829d1df9ffaaf48885291701ac1765090c383162dd13d6bac88baa0cb2d748363bbb79843a1594ec6d8778854a63b7c9ffeb6d1fb17e90f1 +CT: 61325c7e0d29e9ad50b9c0fec02d7ef4 +TAG: 4b2d0caece46ce2496445883c03234e900189c22b54390b399d78ee4ebfbb7d4 + +KEY: 3d9b651e65e9239c9e33aafb091b348161ab797901fd0468aedd014e4d5683c8f3f54f20ea6bb07bb25dd258df7bcd5e +NONCE: 32bcf856a14437114e7814cc +IN: 08a667c2923f87a7db6502478d32280bdc +AD: +CT: 5e8e02cc91c732356bb9f1fc599426a379 +TAG: 5449e878d558beff4bc7dfbb5f0195444705cfb259773b4faec524fbaca37ea0 + +KEY: 2124cedb5f3f2558f8b9a2304a29c0df6102333cb4aa10625aa82cd76ab645c73f3b7cbf7c96cacdcb9e0b738e40c042 +NONCE: 7ae419446a3a105beb2fbcc5 +IN: a305dc4a2e50cc8e7a65a4b10b73849636 +AD: 70 +CT: fcaea620f7e9ed1337214c4b432d9869d2 +TAG: bfc739c8504a4d9033ab1915f46c1bf65c5382fe9ed1c134026ba32c63ca131e + +KEY: b027feb1aced8fb3af27a9fd7f531c30991ec1abd9f230a3e5d6ee9fc6a77747013f8e14dcdbd07b0083d0ce23dfa711 +NONCE: a30a6520f933ff5265e6e305 +IN: a705f842d542cb6957fbce21854755c6dc +AD: 447bdaf34dfab9cc3dd7777ebaf80077f391093bac9817bf02ad98db9d3f271282ecaf0ff19652f92076d1 +CT: 3ddcb07c121b498f1abb73bedb527d4df4 +TAG: 55957a0e884dea22d6ace10e5936cdac891f5b54225349ede5c44715f1064b5e + +KEY: ffefb7770a7cf125395703985823f3e926f3722ca0764518fd2b8996577bec03648c8d542af1c6e36b51174b0ba88316 +NONCE: 4c31394b4b24f6251a839891 +IN: f026a1d352c37b204c6c1138abee9a9a75 +AD: 1e7c0f71a3aacd87ea785521ea31f93b1efd0bdf97952e0b84ecd50c706806deffc19caea312b5a9988454d2 +CT: 23c8bae37db93ed9f55f2903e04b7c6a8e +TAG: 89d0a7e7d921dea5bb54c28e79b612688e42506aa69b141de830c8d63bdefcee + +KEY: 453cf5e4f48ce5a961c94af0e1639c156965970f561ac17fe08d5b75975abe3db87412640972e463290800666be80441 +NONCE: b3e3f9708a86c7cdf139e496 +IN: 53f1b11de497cc6ecb411a777dc3d60197 +AD: afe29e074dcce850ac6640230e6b9f66a64587c5fbe8679144e065d3b1700c721833ba8f918e926c9142f5f362 +CT: 15d5f597be46a19566a72c5e843b77f70c +TAG: a561c3375c096a116a721e9404e555a2deaf3f677a8611694281663274708f58 + +KEY: 3d497f81d0652d475bcd85cf53bda13f79ef0afeaec09dd679a6e5ea58f87ba6576269f836096d5ac034594b17073331 +NONCE: 3fb1664830821e2b524890c8 +IN: bd75c313f5c8f6007a2185bc39d0af01bb +AD: 50744ed959e2b8ba5b5f4807e2997ea0b96ebfcdeaa1c6b33853219844592e82ad67abf6ccbb272cfdba6a3e45c07fec4d4a0ebe4235f11d916771a764d9a129d39f6b84f0b5fb4cdf789ca2f5ea306b25d047a9b1a1e2e90905b6fba472e70b2fa25c96602cfa0031f31c68954d7487507081b8e70f8aa1342cb8b4a98ce9c2 +CT: abe3869ac43fd8b429ee8b8539c970bc86 +TAG: 33fcd301c2bf624bccb92a986c2dd5f2ecafc32649ff550eb5312fc81cbce46e + +KEY: 353c3e9f87b40fc0281869c68d9d9bee5c95771dd79998c059bc5ceda71f139fe447cfdf340e9eac57f232b9d230e45d +NONCE: cc7a4b46b02f4e7f96fd34e3 +IN: 44bcb61332930f606276268ddbf3287bcaedb5b25704489cbee63ec839d7a69533dbfb6e95fe5b4694eb485beb1437f0777774868ecf45c8a5b3edafa1d62a +AD: +CT: d038d67b8b690519fafa7467c9fb94135f9bf0bcd8247cd2c30da62ddf37a6d9a3a9bdcf8ec081fb4469c0fc2798e2e30afede7cda384438fd01e5d672dcb8 +TAG: db2c685a59cdf304c1fb57b66966a5ca1cc3536fe21eb1113c25868428640c7d + +KEY: 3b3786e38e110ec0c8b05fbdb3d9b6d117d1ebcdc0e7d942249fea6baafa31fe5caac227979fc833b104641e8e9ed01e +NONCE: 53bf31912a3ededc01c91f84 +IN: 6de5890028382aafb186042864c5cca1a77ff80ba4f7f0942dcffa1579711093fb652c8d475dfca81a976be8ca77eb9c7a6b49dca1425610c945bf404ba65b +AD: a9 +CT: 886939354fa117139f5e077baa186825ee7e2955c3a74f88af3a86b260ee9f9959a90409e7d602e36cea31e606aeaa8b9229e28f7fa58ace6fd217e5cce1e7 +TAG: 91a769003ec900dbb40ea9c9b959882d822421b510ba85ca826bc4af3b5c42e0 + +KEY: 5a75c97f3583983bbc5eee4a882b766a6708d798a46f71e63b7509af69afd7cf86f9b42df04b626940914007078a8b9b +NONCE: 426e8bcbcffb6b425706dae0 +IN: c24fa29a66197cad518c5a1a76abd9446a8f24c2dd81e953bfc5c00544c119d67986781a1c754224af234b0ec5e44e78610a4420eb78c283e9a56637c35c24 +AD: 6376835513967e4ccaff9a0c56b4d27a2bd0d013cd54abf95fe9a162d036af285ebc9567a16ed5abfa69aa +CT: bc4daeef3ccdf9abdaa75591781685eee3fd7825bfe63132817a7e0f93817f22bfca30ed775a773f5bb290aac3a381a01085e861cab7b9fe4c5143138e17a5 +TAG: 79c779bfcb974ad9a8ac88dce5027df5691a3a1163a5d5893b4cdb1663b17aa1 + +KEY: d1b301c029fe3b81e4b97e08e84dbc03b138f422161c0e74ccbda3172c034b99610f09a9e611f0e9a3ca40af4fcb3c56 +NONCE: 4032c79eb3ee4b63e44fa932 +IN: 71bcf5a5198787b85a66221c22e7bdb9d038dd3e10000555ec9271e54bfefc460ef4e71729ff7ae52859015b49f45df89ddf183fe1e19de3acb032dbaa4d57 +AD: f1cd18ff1e5ad2b65de41e083b5175966625ebebb3031e1027761e407dae4e8e193ffe7dea52ff61147f1b4e +CT: 7c521a703b7d1cbd086bdc316d4f2ff0852c462eeaa1d7a586c561354be9ed412d9d9bd1f78cc85468750f1af09b7b17dc1ee84c926760d63504cd3a1dfa3a +TAG: 831f3552890d997f0a8f2d832b6e92e26f6e865424699f0364a82d86ab7734d0 + +KEY: fdd24bf37b36666a4f641115581ab4bd6b896dd3017006031b3675beed33f21a314363e3a07bbbf4359d9ac02eec847f +NONCE: 7767cff1a096a9f7d8a9b32c +IN: e62b7695dd41baf49d1b356e64c6d5504784380b75724b86f5f3185d1a530664aea0e5f9aeef347e1ea4754acaa7f3c233638db234c0e93db02e0bf988e7ab +AD: 2d650f3daed2564b0df86fa23ed0343634663adfae2c422f80f9d5674bbb63e824f01ad3994834f889133bbc0e +CT: a51f50a6ce77a22ec472bc18c37d08fb28e77efe55065b600e3edbd9ac97f0fd0eec93cd312ec7ef886cb04e1849526f0a38b14d862bcd578b99bf9a007c2e +TAG: 89d83264364c9c84ba705e5549abcd496abed3900f65e3daa012275fed18a7da + +KEY: 0f88e2d00d2c4bd682f1591ea5f4c1a1090180e1195809cb363b27c863360a85b27814e6a724effa44f298430d6c9628 +NONCE: 6e2e62ecb2aa47c7e5921d25 +IN: 91efc710a57adb57017725cfa26d17d3e2993c5ee66942ca42e770a83763e9df8a455bd408dc1e2661cf301f1dd669cd6d5b4d92a886be0f54527779bae8f9 +AD: d060cbe84271e85f25a3dcb6dbf299551f0dcd5783e3df80468636e491c0100f3ec8316f24240482a88bc430a398b0ecaee5c48a274ffb2d835e200bc39ec0aa86a1c90c9e2dcb4217595d48826a81de90eb949846a33fc26bf8886ca0554e1b8f12cbeee36e65e33cbbf610c2d24264619fa93c44c88e0e3d9d368fdece461b +CT: 10d99b98ed67d85a44fa57e706a8b028c61ef17f35f6713613d158cad90e826f90ef036a2190ba123f9b68b352ca94fbebf8ea947e569ad45f00e6a36975f8 +TAG: e345bebcc4a8ac01528bc5f317e5c378236b292c2baab6ae8654245da35d90d6 + +KEY: 1ccec52c77239bdf6ca50e5b702943b23015d08cb1d9bac592b3dec4c96be904110713e52e114a8bc294df26530a758a +NONCE: 38554b7c40027afe9721e14a +IN: dac91fcdb3768df8d5ae9ddba1fe5917c084a5d9e6b14eee9a609cab2da34ec9f95cf2d10fff77108477e694c76f362e29b9a9287d8b190a748ed0a929967ff8 +AD: +CT: e6bcb38b3bfd0b428a14bb3aca01a4a9e54b0853f10bd7750f5bb58d0e7dd18006f8929d7d862e5d6601ef63be8442334b4d51a99219cfedaa31f7ab19028459 +TAG: c4f05d9415840c2325dabbcd12dbeda31e47637437514c606dedfb8ce622edd0 + +KEY: c82ad4c6f248bc51d3a51b958ecc2460a3c64d669f6c485c2309d26abb3fa84644a0d8c28da8091f90184b53cd556413 +NONCE: 35a29938fb7a31225b08d0e4 +IN: bb0045cec5587e50b148b140b6969612425243ed1412e812aa9f4b471ed34ced6dfa9e0acf3e31455893e4ee7e66b4661c6e1f80b7d6f1159c11387ce579b80f +AD: 12 +CT: 5f1854fc2fb11fd721755445a1efa5a28607a725ad71cda9a3464860a6a0efe3f58727c0e0cd315f867611232abd72034dfc2b9deace8cf6cb507b1cd4032b59 +TAG: e40429ca19a88da73a7654d7ed8e0621ac2e504b0245615e262ac70bd05a3f47 + +KEY: b01bec74fe97e5af7db2a0b1432f8b4c069447d2b56dc2668371387f753b03465412213999d2394a4b79873db06c590a +NONCE: fec7de97d54dec8d36c9f253 +IN: 88ab078d03ffacd128edbceea7ace2e6465f4076097445a5db7f0e61ed817b6e24f22874489049bee0c58d0aa2b42b4db0bbef6ec88d032da9c82ebef57c424d +AD: cf0ceb3e80a76d1a75f6e070f5d3fee1cd1e2699434f96e7cb3adce12d4a3148dd433b08c68b9d66962f24 +CT: 8aa3c7478b0cd86fa30870957fb5307345f89346a869d508da9d3a4fe36fb3d6a9b0c3c1bc2d44c8ea31ec028012098d6032085af0b54603dc2fa65ff091fdd6 +TAG: acb670172ec3754064b366566bdccf5056eae132e2041f1a285c5883e7eff4f3 + +KEY: 699a94f6e6eb457b186af58c25118fcea81c8f0ad265e7c16bd6cdca15c9db64bb9a537580ca0474a4b4d54d47412d88 +NONCE: ac3fb6525f4357d831529407 +IN: a7300aa94f3d357cdb272f0a739979e08aad9551dd3bfcd0b5aca6a0972a71b502639e79e1b9e0d22db2f3220b982800d9cebbac3d10d9bf86ea25d3d417fc57 +AD: 19c3d34bb9d57d0f63f14bdd3da06a43a5afe6a8c505f038cb403515876a2765c2d61aa7e4c84e11c999b81d +CT: 8b472f1069ace78172611369b03073f751e5206dcd2ce3b45c431095f303e70c59bfad3af8006e66e4a68f8fa2ffa534bd76bdef089d07dd38988cbf723393c6 +TAG: 8e7c3c2c41b1117928ca1cd0cd48c25c319c18e009804c007d1aab0967c0d0d4 + +KEY: f3a7b8c2a39531d5fb3c97bc9224168aa835973f48243d6f046d00937ed428e5d672e22af26e734f0c24f989fe62621a +NONCE: 65c61af60769672f0eeda005 +IN: 59667fceb2594e002c844a47d2b3935d2c99570b1639f0887fb082499e1d36f9699ff9ef53be3b4236136aa9e441abdc63dfe536e6fc9fa8f332baa1dad577ad +AD: f79036742501f1ac19dbb2984e09cf5000bc4bc0424082376c307b8f1e5bf74dd29c802139d7ea93d55d336464 +CT: 9375a81f016c2dc59a8e99dc33fc0db7ef99ab2f9ade4b0ba000a614ff2bd13bfbee2d4a2338109c98c1147edca6023cea43570adc503da98379326ace89d796 +TAG: f563869420699dfa0aa84751526bd75af1473bd88311001e49230b09b8ef2797 + +KEY: 27611a8f11cb57d08648ec816b5f3c45882dae394200cdfc803d1a52bb03f225206574ea63b63423da6972bf5a994332 +NONCE: a7f617fe7a52dd76ee443dff +IN: d6ccb950515a4a2de7c3cf5a73b568f32fe30567bb22b3b46feb7ef07205d3215a3d689b96d4b9dbaac5a5bd6ecac6ba50314b19b37179fff2557c869950e162 +AD: 777282a98b2f262ed9456fed3610a2028bcc4433eb8f028597d3bfa220bdb0c04882de03a276d0191cd1a125270ce1630c1b94e2ec0021ce5c494d2e0bdb8745e6e94a387cbb31a0898965174bcff8bba105f94dbf080059b49dee71c3194fefe679ef6c00065154ea809293b088c0c3f2ed7824aac72319a4c4ad85ea990844 +CT: 41eacc31aa3c3a282ae7638d48fc7541d2f129e4cb3455df7e60259be9a814c8e1642ea826ac1ec7ed1fcc216a6624e79845521e7a8b16702566f27f7a7f3317 +TAG: b959992feb7005410f9ea6963525e3d9244f038731ffab8da8c4ebc72489f17a + +KEY: 0d9322713cd132c339c38ec7a75862860de304c70486b89b0f587095c66bfd1abe56f0b34f9ca0dac577fd4262616600 +NONCE: 3298d02dd4eb85a98cb935e3 +IN: 5dfedb1d168fe262d35f78d797560b2634f71d40f438c21cdcb8e73cf9884c11570554f55a6abd23d0e7775a9ab385ae6c9bbd67f08d1aec57347a8fad5a4b8c7b042b03c25facbffc76f0b1ce2e6c07d427eaebe71255d661ac8e8bfe8867e2d947d496ce2318a601d0beed02426311ca678d036deb3b4c65b1f89bd644a410 +AD: +CT: ff09fe27f12a87d5208bf246378ee0740e848262442b8b9c7670c8a73fe6732192cde43c1a1246743ed49e15ec63c87dc06eb3e0c92c1f286108b2c7e0754dcf1b9c3fc87efe3683289daabf2db71d8742061f93098788c3c6f26328b86e358507a03af296d2c29009562cad3763399e0e2b89ed440f756c16214c8ab7ddfb84 +TAG: 5076c80fc76c67d6e4f9b9d470cc184db62ea7da49cae44cb3ce9e46c2f2ca9e + +KEY: 2695671fe86f1658d8b01ec856fb4c9d09a0c51a1b994fc87a3f72bec12052537b7429f11f7eb4aef0b128302ec8f336 +NONCE: 9739e577595418c47b9c10b7 +IN: c723c39be334a0761db795076e81e3dd85e37a57258c7e0e10fe0f48dc31bd5e683430aa70531b7c8e3a904e49bec838e760d07afa9f86b2cf78ae90f612c4560632acb7ea2d89fb1fd5396d0337111c429cdba99c6a52e863e8603aac24a83302ebf86ae69a212cb938e12085cbf73a28f75e4422995a5ec8705b12d4aa8b6d +AD: 31 +CT: 1569b20732ee6395e605217e1cb419ce57496ba6f6e889bdfa3c93575e969eb7a0410c7930b7ea146e88577376d84f0e824b62890eb84bfe768a1513a12c2958ad1835bc1eabe602cf40f7812c7dd7da955567242cd7512090fca685fdd7306bd98a908b09464961114abbdcd610c153637400a1f81825cfdf06505947fe54ee +TAG: d07e14a62a32ef1933abc2127cc5bfc1e43bbca663e460409c6faa3a4ccf99f3 + +KEY: 1785ef6e7016733dd1952b3268639f231e7afa973c0a3db8780b81084c67a1783200149a1ed849ca8b5c14c7b1798b4b +NONCE: cdf48b73c3c8d8625e52fe11 +IN: 14002f17e056d7f5524537cee6c2061e2741c01a6f9a82e2cb1747887875860d51bebf8d9b63950a051f6b228ad7567227f8a45b9fa7c4ab47eab410125303defa7e3141bd9bc5bf4ed56550801ff3bfc2dfaaf499c192b1e18879b2f59e1230778132818df8f6ad8a3dce9a1d11c98075b8b4e560edd9b5ea180f0424ab3706 +AD: a35e86e22e9a3df65e4c08e5175b4216fa9895a1be6252de911cf98349841494617eefaa007759dad7f337 +CT: 99eae989435578cb57715a7457da31b807b8078a59c2332a0a866eee9da5188baed3f517b6808095f0067e9b4b91cc1424a464f0a09fc946adbe4135a17b0e8e545d2046f81cdfdb233aa3520797319c0884ccbade8235c32d195e7b802017f88ddd86fb630de19eb97f4bf91029c001fc8f1cd2189a8ee6c120e9f1682a8703 +TAG: 1848f0b163e7b0d270e2a0ced288ea6525697170aae15038f3dcbb4ea49ef843 + +KEY: ba9aed2bfa90eaed9b27a697bb44c715c0209cae6b2c4ddffc684bcf07ab51b0e096dbcfa26c18fc24b63408317da567 +NONCE: 4b850d6bfa64520f1aa1e79e +IN: 5bcc2ea4d729c84340c5ceb827f239578971c595e915f0bd9d49ed51d723f8d0e8362e69fd11466230bda0dad57ad724307edcc621ebde1e57fa91fee206d81d2bb6ead94b4a804f74b6cae979f66bdfa4ad93d107ccf114c59cd3d261aa6e2fc0dfbd0df5f7c18e80d0699cc1712abbefab5029e35549d2919d0f937d444051 +AD: f80c759062e9ed0ee597406aedbcda9a14261d66a9546f1c939d20cb1d0d0974fe7a9b33d8c93287a6a8d60a +CT: dae4fc873d302c51e55910e67482bb80ac68e9bc6ef77cb3e57a31d85fe75f9071d0b64026ba16d0b68fa9c0b7e958cf7682bcd329c4174ea0e3f3f9d2e65d82aae1350a53ea7cdcf9ab848b85cd731751f0e2917628e5066f5b1ddebc7dbda5d2d37e46a7a7ee62bb49c4431af730f9cd3da4c1d0e5f8593d8c99803f781bee +TAG: 58b42e9117fc8cc2ba5cff74b0d92e8b381a444fa837018b15e9514fc4319fb4 + +KEY: 37235623acb0d650f905f106dc3bfe6fd83192e53056de8795ed8d20c6e58e5efd84584007ecb17de9e76b392e12fcd7 +NONCE: dc441f1c743a92c4b975c6b6 +IN: 960ceb8d80774bd88b7c5f17042ad2e4baac71b4021c548458cffcd9a049291cb0df93076c115b54f9af878745acebc6e8f04666d053b1ed980728043c4fe7f67b2bcb0341d8a4973ed126342f9add14279f8402cbbffcecfc847379dca8a68ba4f2f26141acfca7f3ef558dbaf04629f0f46e43246b19d875be452f14e7bf56 +AD: 32579218062560f15ff966932838460f99099782e79f1f8c41cd9f6eb59b4c2c3d2dae9cd199fe66d74c7a9940 +CT: 49ad8e24a31e90ab1f8dc37dc51dff0f93f1420e79eb108f90f800274a5aa573f64e274cd52f1dbfdee363e4f86e1457bfb8f87ce57aefd34c3a5a3a93db4ebde3f73a3b4c202c993903ab378ae71042ad238e94f400c7ac1891a9890b19d445eb1db60773a3ea165f7c4b2bb2071faaf588daebac7ce09ebfc88f4d9232d9ca +TAG: 82f908b837a5768598982f860ecea16aee84427371c4de1f1314749b70ffc173 + +KEY: e7fc36c9fe87a38f9bb4ca67723267e80e16bf39740eb1090234a473d68aed9c96fe2f96e539795eb042276aec5d7505 +NONCE: 83d768746d40dcd695e49ff4 +IN: e61f0e02a70249b62ec9a8fdbaf6622c9c6316599daff421f1b19815707b67587d196b7e1452c7d7609f108ea946675ac5d97ed215b92a451aa6a11717ab7819f84848151007f37e2cdc8aa99969c3d5652aeeb65fc21b621865f47f44eb2c528ee1142d11f513761a6bb2d169126503db5b263a410cadd2773ff931a032a885 +AD: 59114e9f21b380ae6068609ac36688e6aa7c2533cbfe07013ad1b6663bfa42e39f20e62b45c0faa256c1d33caa9f59b1e30d8502bb7148d051451b3d0265cb9fd0d82e4f4e0489ac606956762d8e7b70abd7eca413ddb708f119c342b3d0d5df673769d8df281656d909b68b6f6438edd60339fd84ff69918b6036ad12a0a588 +CT: 4f12807736c9ab32a2be2e00c9a0236394a8bcfcec6037e7582af462a73bf10aa73bd90e2bc24b97f7001ccf653574aea294bc7b30b77540f475e0e846ab78ffcfa1fef28058e540fea43d9017d4efa05c837611b2eacf0034f26cb7903eff7874973c6da7843892bfc676170a75f839e297dc7f04c74b40f4bda20a45b2a352 +TAG: 9b05aab44ba4d1451f14e087be626232ed11c4ed04081f0d4d47ab593fc619b1 + diff --git a/external/boringssl/crypto/cipher/test/aes_128_gcm_tests.txt b/external/boringssl/crypto/cipher/test/aes_128_gcm_tests.txt new file mode 100644 index 0000000000..eac9aa9270 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_gcm_tests.txt @@ -0,0 +1,531 @@ +# The AES-128-GCM test cases from cipher_tests.txt have been merged into this +# file. + +KEY: d480429666d48b400633921c5407d1d1 +NONCE: 3388c676dc754acfa66e172a +IN: +AD: +CT: +TAG: 7d7daf44850921a34e636b01adeb104f + +KEY: 3881e7be1bb3bbcaff20bdb78e5d1b67 +NONCE: dcf5b7ae2d7552e2297fcfa9 +IN: 0a2714aa7d +AD: c60c64bbf7 +CT: 5626f96ecb +TAG: ff4c4f1d92b0abb1d0820833d9eb83c7 + +KEY: ea4f6f3c2fed2b9dd9708c2e721ae00f +NONCE: f975809ddb5172382745634f +IN: 8d6c08446cb10d9a2075 +AD: 5c65d4f261d2c54ffe6a +CT: 0f51f7a83c5b5aa796b9 +TAG: 70259cddfe8f9a15a5c5eb485af578fb + +KEY: cdbc90e60aab7905bdffdfd8d13c0138 +NONCE: 9d987184c4b4e873d4774931 +IN: cb75a0f9134c579bebbd27fe4a3011 +AD: 7dc79f38e1df9383e5d3a1378b56ef +CT: c6a899758b6c11208241627c8a0096 +TAG: 7525125e650d397d0e176fa21315f09a + +KEY: 819bc8d2f41996baca697441f982ad37 +NONCE: 08b7a15f388fafb16711ce19 +IN: 9b1ddd177d2842a701b794450e3c81f151f195a1 +AD: 277c372784559784b0e047c6f8b7e9efb6f7491e +CT: de9b9c8fe09f705f558c62dc6d40b75e3aa625b6 +TAG: 52e2d2f153a4235eb6fac87ff6b96926 + +KEY: 682769d52fa0bfeaebe0d0c898d3cda7 +NONCE: 6af0738b249d09547837883c +IN: 3461523cd98a6e8bdddd01150812e6c58d5cfa25d385cdbbc4 +AD: abe8302d7d5595698d9f31011c24d4d180a637597098361354 +CT: aa3ecb46b9330554b36d0cf6f6ac4cf5e27bfd5f602da1b3c9 +TAG: 0ba547961eba5c58726c418f51d31311 + +KEY: e2b30b9b040bce7902c54ca7eec00d09 +NONCE: 28ccf218e8de56ea91422a25 +IN: 483080d7e2fb42580dfb862d2d266fad9fdce7cdcdb1158d415f84b6e269 +AD: 9f06fbe67eb2ace15c8011032feeaf72fdf6d316e1e08ef4cc0a176588af +CT: 67e1980ced4cd232ce893938e40b0798b17a1692476342e520b480a18570 +TAG: 9994185d4329cfa5f4bbeb170ef3a54b + +KEY: eaafa992ef6dbcc29cc58b6b8684f7c7 +NONCE: 1ded022dbc56e9ad733e880f +IN: 900951f487221c7125aa140104b776ba77e7b656194933fa4b94a6d7f9722aad51b2fe +AD: 863ceb297cb90c445dbcf2fcffe85b71db88d8c935158f697023e2cea103ec39766679 +CT: e0b3aaa890e45f1c39ad4f13ba7592f5251d6a02ca40fe3633651b35fba74a579f48c5 +TAG: 5c95fd941b272bafbd757553f394991b + +KEY: a43859049b2702e8807ac55b0ad27b0e +NONCE: bbe8c571342cac7fcc5d66cd +IN: 8673d6ee2903265c92446ce110d5bb30aa2dd1b1ac5558029f23974acb8a2fbf4c74858fc73d6104 +AD: f77c998ad3ace0839a8657e350bed15ffbd58f152a0dc04ffc227d6beb5738ad061d0f83c2a26999 +CT: 40e201a513979b093637445275b2db5ed4cb1fa050af0e20e43b21af6bc56dec654541e55b295b72 +TAG: 41bbef45727d19ee544fba5b360312f0 + +KEY: 68fd608c8697243d30bd3f1f028c5b74 +NONCE: 319a210b33c523d8bc39fbea +IN: 2c088f38f7a58e68bdd92632da84770303cd1ff115d6364479fb0aa706571f68d51be745f5c1d1b44fa1501cd5 +AD: 1417a65249b85a918622472a49df50bdb2766aae7bc74a6230b056549851b3c2f0cef727dc805ba2160727fbb2 +CT: 9d376b147620c2ac6a5eaa8ee44f82f179f61c9bc8acdd21680a7ff03acec953437a3cc9660c7ecb1204563944 +TAG: 05a4fb5be11e3edd89e34d0b7132d0fa + +KEY: 6edd3bd2aa318f78b4a51103cb08d489 +NONCE: ef0027b144691bc9716fbeca +IN: e98f2f99680dc748fe0b57390df38a99950faaf555a888d463d005ef4e4b1c22663d3d3daa812b20ae35ac934c2e187cbba7 +AD: 97337902507391de0f15c88462aa5ffc5e4760543850719ccd8a0cfef89484d8095c23ff8c1d06eae4ff6d758c95e65cc3b5 +CT: 3c54842c2099b73daa9c3f1cb64bb913c0527955d923510f3f3046df471c1365db97333bc5a86dc7c5f23047e938fac976c0 +TAG: 375b2a25421434e5e3a021d434fb2d04 + +KEY: f70482d53d3ef70cdc3cd3c4a37aeb2b +NONCE: e69d3de363e225749cb1666f +IN: 4cb68874e69125e1a6f6e68669b48317e1b361d0f7f95ec4cf613b7da2c835832010e8f95eaef4e6800b79bd86cd7cda869d2df258c267 +AD: d72975f15721bd0957f5cb1edecaad2d1ef047afb0e779035f777f94cd7ed1bdf8ca9d4f357d2a1e195f195e7483dea1476133235f7e6b +CT: caa1e48decbda18e314057c5ec32f8733a5cf03ed0d05c3654531bf56faa70751a6c7f70fbd7d39f7e9775a772aba8fe7731cd0230beab +TAG: 47d909cbdd1c7f8b485fc3232bb7185f + +KEY: 98a12fe16a02ec2a4b3a45c82138ae82 +NONCE: 4b3404684825dfcf81966e96 +IN: 899710fc8333c0d2d87f4496436349259cf57c592e98ec1e3c54c037bc7ef24d039a8c573ec7868e8ce9610b0404ea1b553ae10cc8cec26468cc975c +AD: ea1a99cee666bf56c8c3667ef4c73c2e1e6534800d6e39a97de3bd5d39068bb3e2f74f96c03463afa18f1ee88c21209bae87f37e5d0269b68db370fe +CT: 0431b7fc4889ae401eab5edba07a60f9682fe58419d4140cbf4f20c62d79d8a3cc1f23fabead0e96e1c8c90929756ea1efab508336e1d0ed552eafd0 +TAG: 01053ceeb4f9c797eef9426930573d23 + +KEY: 6538e8c8753928960ffc9356d43306b6 +NONCE: eee386a2b1e310665e335746 +IN: a92eb9a93a90fdbb2c74dea91d273a48efe9582f8af7a4e3a377b114770a69ca45421959fcf36107815e53dc61b7bf018fc42965fb71d1eafce0961d7698fabbd4 +AD: c5e572e464718398374c8b45ff8749cd9f517bbd97767f77a96cd021176c49c0acec8b055ef761f49aa6d910375a45b2f572cd5420b99153971a682b377ac88f09 +CT: f36353de609d0b5246f64a519d89a4dfcd9d53325a2d2cf910e7692e68391b0357b056b944e0b53e41568f304bea8822f9ff7a0375a5a8087509799226862f707f +TAG: f7f9b891089d02cac1181337d95b6725 + +KEY: cabdcf541aebf917bac019f13925d267 +NONCE: 2c34c00c42dae382279d7974 +IN: 88cc1e07dfde8e08082e6766e0a88103384742af378d7b6b8a87fce036af7441c13961c25afea7f6e56193f54bee0011cb78642c3ab9e6d5b2e35833ec16cd355515af1a190f +AD: dd10e371b22e15671c31afee552bf1dea07cbbf685e2caa0e0363716a276e120c6c0eb4acb1a4d1ba73fde6615f708aaa46bc76c7ff345a4f76bda117fe56f0dc9b939040ddd +CT: 049453baf1578787d68ed5478726c0b8a636337a0b8a82b86836f91cde25e6e44c345940e819a0c505751e603cb8f8c4fe98719185562794a185e5dec415c81f2f162cdcd650 +TAG: dce7198728bfc1b5f949b9b5374199c6 + +KEY: fd1dd6a237a12d7f64f68eb96890c872 +NONCE: 459ced97ebc385ab3a8da8d5 +IN: 04a9709fdc0a4edb423fe8cf61c33a40043f1a585d5458c7512ec8e4e066a0f95e2e6609abf3c95a5d3ae2c738269533855daedd92eca20bdedbbd5677cd4eee84b7a1efae0904364f1e54 +AD: d253b829a2fbc5877b0fbe92e7b79f38886a49ca889ae72b91f2c3aebe257a3ffe0d390b5d320bea22d6a5536cd9213612f5ed6e3b0ea33ac91cfee284cb25eaaf6b85b15f7ca894317182 +CT: 4a565d3ba4f2ec461c9bd8dd0f96bc00d2a561bfb56443c8cf47681bdf1c61f55854bea060c4219696cac79c09aa9400a7e5c59c6b6ca556f38c619a662905fc5f0e8437b906af6138e3fb +TAG: be5f93201d7980af4c5bceb24ac1d238 + +KEY: b09a4d99112e1637d7f89a058988b417 +NONCE: 74348f7126c0cac836e9de5d +IN: 6b3c4cfd1eb139b62d91ed5d1d8b0f3b52278d5c48787ce46f12b9f026e3eed1bfbc8c6684c6662f06614c69440b3d7cff7c46b2e4aebaa4b5b89236a3cc75535bc600104f240d01de91e0fb3bcad02c +AD: 7883ad259fa5d856ce283419f6da371b444b9b64ea0ddb371b17ec0a9ada27b0eb61b53bd3605f21a848b1e7ed91162f3d51f25481f32d61ec902a7f2cbd6938a7ce466a37e4467e4ec2b2c82b4e66ca +CT: 5e1b783b20fd740310333eddde99a06b5740428cb1a910812219fabd394b72a22a6e3ca31df0afae0a965f0bc0ae631feeaa5ce4c9a38cd5233140b8557bde9f878e65e8932b9e3c3f6e57a73cda36cc +TAG: 784b73ee7824adf7279c0a18e46d9a2b + +KEY: 284bd8c4b5d7b16aebce1b12988fa1d3 +NONCE: 7ff05007c5d018b17562f803 +IN: 903416331583dcbd31420906c64dc76e14d0c5044d728cd9b605b531ddc350fdaadeabe67d08f0b4c7179f82a1044696716cd96459506453141e9ec3130e893d8c2ff9b8b4c241b73866ca4fc1f712d17d7a88bf4a +AD: d0a1f92f80094c1fad630ca584edd953bf44cdde404f22c8e476df8708a97a0712e7fbd8054caa7d65144d0be3b30442d0dfa5469ba720afe1d00aa6bb53c79c1c178ed42fce596eeb6c638c8a8dedf76a431976c5 +CT: 9bc3708f70a68fc16bcc33099325c821a0ae9a2fd0a6a98382fa21b42ddb3a9ac6c34a13c4805d3beb92586cdf0f4dce3885793d49abce33190685e7009a79242dd93594722a1ceaa44886371c30bcc8312fa2bf67 +TAG: 3fd8a4d760d5b878852b1ca2d34dde6e + +KEY: 6d76dd7dea607a5cf5c21cd44c21a315 +NONCE: c1d13e56b080a500f1cb80bd +IN: cb959b92e777f835afc4ae4149b190638851238b7b13c9bf65343adb3130e8ad2356101037f30997d4a5fcc0a1d6415210179fdec881236a799f6e90dd43ea3817819b432611eaafd072368b9c7036c7a88c8b7774a8ed986134 +AD: 92a2bc3b6b6ca9de0cef10d8bdeaadf6f54782cdb2b09e66cce8cb5b56895636e982f7a3c7bd9d221ade62c9ecf68bde70becf683804386606ab1c48ac764c4e11620064545c5beaa5911c118856dfc5cdb8df50052b01762c6c +CT: 522ba9bfb47efc624cd8933fc9e17784919d2b3ccfaeec46af414c1b316355f65b9f9fd7f0be6ac3064b4016e43b8fb2028459f0fa0d81fb6656be0ab8fd841d05d24682b4a57c7c59d89af384db22c2f77ce10abc4d1c352a1a +TAG: 5ea4a77381679876e0e272b53519d533 + +KEY: 1dbcbe45a47e527e3b6f9c5c9c89e675 +NONCE: 98f2da8ed8aa23e137148913 +IN: bb23b884c897103b7850b83f65b2fea85264784737d40f93ecf867bfdba1052f41f10d2c5607127da2c10c23b1fbd3a05ce378a9583b1a29c0efbf78a84b382698346e27469330a898b341ec1554d7bf408cf979d81807c0cc78260afdb214 +AD: 46f1bde51f6c97a9dae712e653fcac4da639d93a10b39350956681e121fb9ea969d9dc8ef6ddfb2203fad7ab7e3ef7b71eb90b5089844d60d666e8b55388d8afb261f92b6252f4d56240fe8c6c48bfde63e54bd994ff17e0bf9380ebfb653b +CT: 0d90e869d2f4c85b511fdf85b947ba3ab75c6b1845d8191634770413d7574a6fbd9d86897cb3d3b5d3d8e6f74fac3bd2a9b783cb16cfbec55dd7d2f7fc5c39fe85d39bf186a3fdd3564bc27d86f4019ae0cb73f5f516b602331433689c1b08 +TAG: 8777f2002d5a5214a7bd8ef5a3ccfbbb + +KEY: fe33f47136506e5cc14114eb62d26d64 +NONCE: 9534a10af0c96d8981eaf6b3 +IN: 3ca38385513eaf1fcd03ac837e4db95c0ed1a2528b7ab3ac8e09ecc95698d52b7d90bf974bf96d8f791aa595965e2527aa466fb76da53b5743eda30bb3ebd9f6a8a7721fbfe71fe637d99a7b4b622e6da89e0824ac8aea299ea15e43250d2eccb0d4d553 +AD: 50b7bd342df76bea99b2e9118a525c0f7041c7acdf4a3b17912b5cbb9650900246ed945cfc7db2b34a988af822c763451ac2e769ec67361eded9bcab37ac41f04cdb1d2471c9520a02db9673daaf07001570f9d9f4ac38f09da03ff1c56fdefe16a855ac +CT: 927fe3c924d914a7aae6695ddad54961142b7dd5ff4c0ba5ca3e0cf3d73bdb576afd59bd2b54d820d2a5da03286c124507a48008c571c28a0ce76f0ed68dbac3a61848e7e2162be8e0bee8147b9bf60da625cdab8601bfb37dfcd165f533e94a32c26952 +TAG: 9bd47a4a2acaf865a8a260179aabf8ad + +KEY: dec1b34b7b81fb19586c6ec948ecf462 +NONCE: d9faf07e72e3c39a0165fecd +IN: f7b0bbe9f0ff4dcf162792e9ee14d1ed286114f411c834ad06b143cadbbe10a6fbc86f6664e0e07ff7c6876d4543e5b01ff5ddb629f896c30c8cefd56c15d9f24dfd2ed590304a6aae24caac5870ddafc0e672ac3aacae1867891942998c712d45efbfa4d99a8a6f03 +AD: d3c4fc4838cb3cda3937455229ddaf1cb9102e815cb9f519a5434677c68b11a0bae1280faee82f1a5bee593e669e6f81d5ece3675b8af63f1491bb298531aacc940f53678ba56ae96fc66be92b904bc35f2d5b68b3ed98569a4d04e8f8a9689ad9fa4b51db0938a9f3 +CT: 2f44ecf549077b98ba551819538097bb80304a55c48ef853e20ed8c3f808dc8cb5eb41c2463d19fed2606b59cee4b458958ea75715f7654146df4519dc63524a0569a00d7bbc4b32a372f82d955be5f190d09d35c267da1017e8b16096ae84f8a671b45aaf0d1ca59c +TAG: bc3af80cf9388d35deadecff5455d515 + +KEY: 021add6030bd9f3fed8b0d1f16f83783 +NONCE: 4e460f51fe6b5eb9558c4571 +IN: d9aa1d0db5de536cfbacb59bb75c592ae3f34a5f9c5ff4f22d14e8e4bd0754af19570221893797f60c89a251cd6a19c2953662dca51264afc21099ed5c80077b0e10a5295b3c4c6fe47d3c1c84fee69ebf7d8a7d9b1b338dae162e657e6cf5277ca70d47b9290aa7efe67b0ce574 +AD: 38d99cfd7578d40ffa1749d5fe83500362ceee76c5af38935806837b2f2d1b3422a5057bf617b07868dd95d8e5f4a24e74f96177d53a0275450b429a2b1f364805030765e376151ae35001d6a4872200142fdce82017f3e976ab0edac1a08d2649d297648320e7dd9143b554fa3d +CT: 8863ad51578fd1c9dc40702e34236adee885955f0478ad9a094a6941f95f900e466882dcd5b86e1563ba89aa105f56f3ba5ed860ec3338ee1b750a2f9332acb3f0f61718de7e40fb80442d046b35f147f178bd05362f0559a20a53ebbf78e920fe14c9d80d1c9fb21bee152f8ab2 +TAG: 614539247fdcf1a2aa851102d25bb3bc + +KEY: 311c2045d5486bfadd698e5e14faa58a +NONCE: f1cd8b373cec6451ae405618 +IN: bd154e428369aac5c13128d29bd3031364939abd071c34bacac6ea7292b657b794b2e717d9bcb5d7d01496d805283fffd8f7de6a3493ddd8d1dd7f58835a44d43ea22d95468d1239ca5567d6c80bdf432fce2afc544a731a2852ef733667b9f8f4f8923eaa9de3aa32addddf99b607efce966f +AD: f70cb7e67b2842207df55fc7582013bbddff8c7f3bd9ebbaf43827aa40f8490e65397934ee6a412de6272cd568566ea172789a006a92e5920140ca5f93f292b47dc262cefc66b75543f94365c08795b7c5e9c6c29b7dc67b2532fbf8a6487d40a3eff504e75c3f2bb2cc3969621028e2112e67 +CT: f88f4ef0431d0f23911aaa38a4022e700d3a33c31e0c7bdebe00f62ca3b55d358385de25ceb0538242871eb9c24530e557d7981fa0182436e1e49272d52689541f09517fd147a8da0f0d2bb32d54911a36eded0b87bcba54d6842edf461b45839df1cab5176e2c82c871b3be4ec1bced67ec5d +TAG: ae8d847f106e914ffadbdfe7cb57beba + +KEY: ceab57de6220b2c80e67f0c088e97b36 +NONCE: 8cf438aeb0cb29dd67506b9c +IN: ce2a7a5663449cf6e0068085e3c373c5ca6f027544e327bbc09ac00f1571268bee186d51a00bbc16da7429e4d3d5235d8d54ac96b6ecb2fb7d77a6e5b9e70d431dd4dce78ceb972e9e4b63059e350efaff841c2c42bc29c139b7fd070097556b6281b58e074d5271d9f66c6744ec6dd3b9db2f4a21aeeb7d +AD: 03e464d111ac9228d39d22a00120c6ee671fe5bbf462b1ee3fdf348b34999518998ac4e175ed48189c29b49b5527c27c43094eecbeaeacd3cdb48cd15aa82573e884a7b97bbcdad610a6955f7d8b04f6f98a13a907bc2bec4c940b77582b248f5fced1771f810977b2d0a4fa48bd4d78e4bc383bb92743fd +CT: 1fa9c379c78b92fa3c1e478443ae38d7b4b50235448ce2a88467514bc9db95844ec1baf4dbdbd1b0720e377d05d82c3b58b52af8c9c50417b39ad225e373c7ff18ac5a6ea5d182b255f1c8a2766e31e3e4e3d55dc08dfc64b818ead40a0e824b06ab24f0dc9f4f0c383db7cd4d40016b31701bb401b126dd +TAG: a9a885578467430504731d1a8f537e3c + +KEY: 585bbac0ab4508afb8b72d84167551aa +NONCE: 774c82af194277a5506e45ba +IN: d788112213d2b8b5b66b056e8b3e344a7876f6193b59a480c51fc04d3ec2e5166344c833187b14117276fd671a20937a4553181c29d3d85afe385dd86093708226f082a2ea4ec3288f372c772ca7ceae86b746ff428e8add17b0f34f8553e3db63f55224c39edf41f138a2c28be49d56aa8b4c93502b9794a16310f78b +AD: a29665261a8eb58c88803bcf623dd1a14e76af49ec5db72a267f2ebcbc479385fb6b32bafcb1239515d74a8282b228e83daf282d1ab228099b315bbed0f0e6b3427e029cc28c025460a8bf0914bd584c13e7de7830ab77fb4a9258dfdc9fdaa96ca941546477f04cea19a365a27de34e23e154e7419aefb0be0e871bbe +CT: 24f2856e4e40c0b2b8b47e43d94c1faba498884f59d2ae1cdf58c73770279c96feeee3025ec698cd8f0ae25bf0c9fbf2b350674c317e52bad50aa6ed9845e194f294eb71ff192604af50ac7192f308583a3edaf6c7aeb588990be81b801dc916ffd621dd4016e2b76e9078c89fac9da39f3a88f6548006a48b0199a732 +TAG: a5c8f9daa30b045bd3e1c1b01f438518 + +KEY: c5d727d159dd328b4160ff45a183226b +NONCE: 881c0802db519ce1595573ff +IN: 88b4be77bb8a2f37bc5e84ef9da92a4b8c3777dbcccfed13b97e93c19674c8c3f13119363ace377a14e5f36501ba9a3898fc09340886d91bf0a17ef0d028f2a92ec150071623a4a5db8e56e99e764629679943ea879ec7634fad1480e8617fe834c26210276d7db208b13f9b4c2060f2867aacb1b47c8e110830beff721dd8d120de +AD: 5f6513ad3d490f784dd68ca1df41e8c8e1ab9a240ea8e9bc22d0b1d7353da94d5d37c94f0dcd1a2dedd6d8e1c79a383e7e214cbb6ee2ccb7c6d894ffce5d01b6cf13876ae2648d36adccd88710d7d2ab6d43826d37ee0ee3b434972a2cb8f4db1c3304cee0a352bbef76f05de0e6f55a410eea5e697afb197f2483f0200d0abee224 +CT: 66bbee209eb11c675ecd3303c38cf1087b010c532e1357732c4911ca9db78c67805c95c829194cd413b635a900a08454c6eb9cfa3597ab531fc9ddfdc5b02b290be2a618df7d03b1ab465d6d03e8b87a430bf4e80d8cb9916145cf2d2342a91fc79defa151b1f3c695608e76ca2abc4c0383897f1cbb9d4bd9969b2f33813e2b5502 +TAG: 43daa08e6eac70e3238ce655adb65005 + +KEY: 16af56326046c92afca49fe173d643ad +NONCE: d32a935b4e56472d92d9f2ce +IN: c49c8e5769670384d23d9af9834026395d3f3bd32d88e61ed06b2e00e52a5ae4fe3867993c2af95203cd4006470a89677864431fb9edbed17412913bad4bb3eaff0fccaa150c9b13f83b9bf06698af844841a640d6f94d845296638ac27fb5ed87c310dbbd36415161310b284b8f84b4e025267906e0a4c822b76a682d44a70f9afde9bcf48ac2 +AD: f713886f4086026779a7e479fa646cb33574e6c977d70b8da49c8fdbb395dc7c149a59e219db8e4fff053cb00e2a1df9850fce94e52fd34661fd3d4cd8ad3ffe0b4bc7ccfbbf42eeef3e30ce13cdfd77dbd067ae9f5aebfa068f6b7ae2c17ad956dc03511dfcc38eac9fa3c0c0e9a340f5c58e39d868b77dede54fea1173216c0bb8f0a6c2990f +CT: d5d7d1ed0ae3e3481e2ccee201857ce1f427734fbb4fbe82a2b90601104008b8ad4daf74514b8ab3e42b6f6b509159ca04489b1175ce1e3fe33d36ea521e0aedff8c69fd00aa588d7a2eb9d2d551e2b8fea321f573e2a1df147535a873d540a3169d3ebc099ea6c33cefc04a2d55dc2d47237b95ad269fcdcd3c3750af426beb4edfe7837b413f +TAG: cbe0fb9509c224bb0e8e33f7ef9b49e6 + +KEY: b3df227e6dc2c846095e2a3b825d7645 +NONCE: 578bc24ca3845e23204df661 +IN: bf69be81cf0b340b006badc9f644d10376f4f9a7a78c997edb8729e3786447f21e97e4c1e0c0c74e01ef655d0a84ffc04ff7c6712ad65adc9a0da2e3078d4c9e796c9bcd71e7a9da26b987990d366b5e00a23a93652e10942e07a6aa01375af27080c9cbab5f554497abc48260937a6fe895361e79cd3d5e78c1a65c6723d4a4fbe9b3dcae3c05699cf6d3fb +AD: 00898eedad307fc017917a3296bcedabaad8a505edd34e93d92f3b61797ddccf3fc31144ef70f255be3b0c165c97eb8706f14c495f4aa9b3f15d2dafd65bf6741d67fe240967efbf0e75e610db9a8f722035e039b5e9246d258084a04c12ee8ad1668032f8caec737481fd894dba2ef702d3e6089acbb0fe0bdd6daa2a5cd47fc62603499fe3ea37365072e5 +CT: cfeb249551a695ddfec5f789e7f0a9f916abc8ee01d6233c32744c10a09b5b19ff9ed15e9f10de8f93c8ca1ae3c34e26fdbbb7f3b0f5f8b064501830d3cc982da99b294ce51bd33085c98b0ac0bfe44a8f4a5a26511afa3461aa88b770f076fe119ec90f33d8c9e7777f30b8cc95864f06e04dd8e328ad7a2c7dab83b03abfdde065bcd0c7d6dd47389108c4 +TAG: 3dedd1054f1a29286a51817264317b83 + +KEY: 58a57f04d1d5cbdd1bfbe01dd5f7e915 +NONCE: 47affabd7dbb4cce76661081 +IN: 5f82d481a6a3856c6f0be2aca54d666f16de88294a4d763134dd51ef03661bab45da94b9871d94e5b574a52214b22c92cf9690ecbffca9b108fe796abed9e608778c0b99d7bea1daec08dae89d5f7229c04fd52cc906b5f5b9fc0f0fc1e0b2272dcf4865286ee22bd9edcce1afadb579ec72cdf6038cfc75c2dbab5a1fd64b6f8e200d1ad0afcf25863293fdb7276648de +AD: 4b662822b48005fbd85bb99e6a946eaa74403909f646d914a236eecc5f4558b60b2efb1584b1f32d936b90428dda6568515801d21d24d6fb622e6463897c70be01f81fef741d6dd5c6556d163c3f048abe49f21817b41850ce79d7ec1fdfeba32935b58d898e964fa4b36f79c0f1f560b0afec3887ab325e1a025fa7662f9baf8e08a9ee714b8369621a2f1e6d2e96896a +CT: 31ab08ce0aaa883628f4b33369e5f6e5a54ee4a6596f25ecd54eeea30e81b41d357cb6c671adb6acd3d4e6654feb2ab1f3259692502efb33c5121e0852cbcb2dc5d9a4c65752debe9c4bf5e995fc909a2881621d46cc220806703795e61c0fe74c99e3c1230521b1f97bcbf4e95326e2d581f0cc879a2fc06ef88226a4413f9e9985edc913c418cc198c4df13cd46afc24 +TAG: 1e54066c6cc37f35c62b47426b609457 + +KEY: 64011470970333b7b677d4ad8ebf3ea2 +NONCE: 17031c5133a426d96de93123 +IN: 882cac1ece2d22a1db7f8339332379eb68516c8b7dcb3c089a5bfecceb49f48a169215313686eb5708135f379d89962af478cae865841e0c97ab47a57a456f634282c4e03c99abf7f7cc4e8360deb48160288f06e96cb09114877f9d91dae98828285626a1528aac87f39cfb8ad3db344fe4318aeef6f6ba14bd1edf9caab548c09f8eea091229a90dbc4b0fa34fda2bf13d300a1f9c +AD: 0394bb920cf58806b909d90c046402c745f6876af85d8a281081e22a1908f8475126594b39a0e191a070bda7c78d30dc4867e69ea522cfc962fa5f9915daea9133e998eab22f32a18957a3cf7d91c6f3d54cea94875d60be694ee841fef01e69bf5997ba4f25e846558431eb592605265f235211c2bb2d4807278f4b9c314039d0768df24e9c098c6a01c689d6a143073fb1a29f4400 +CT: dd347d6a3d4a71b2bcae0a0c690ca311f012c6ceda4f7fc054b8f9b59bad54237b64b93331b99f1305801640a68e7d50cef581a57ff2564c90995a8dbf57fa8cff046d0b946af5f68e0aa3d73262965622fe6d35c78f949a6cf9e4f62ba71accbf403b690e31f610305faa6737a19efba1e1ee97084cff2d125bd69a5a4ff99aa399df650452daa835b3e54114b295f00d94fc60e2f8 +TAG: e5e72cda6755bfb3a44377945adb5ca1 + +KEY: 4852e546fdea545d7dd12493a687e895 +NONCE: 7a3e136cd961191570c1b0b7 +IN: 30c10d7a63b614bcae1b79b07c252dc55f322554ac34ca664910fe4a0c9a33e30698e124d91cbb55cf34e931807cbe591a87667f2284c1c18dacd108163aa7a82e274ae659c4ea144191e3fc0f82d4cac929969a50b98ed9fbee52cdf465a1f0535d7d7df15a9a6eff3f4a14e254571cc47f82716d7a835dfa839213677c4da8c8623517244891993ad5956f65d318d9bba16f1eb54d2974a741ac +AD: c5ded7f545d2eaccbc2cf5cbd1b38b0ec3b6bbc054ba25a16efdd448e5a47b0085974e469c1b0df22441340170d6677f5158e4ccd71446d7ac73dcf5fcfe4ad7248c4ddcfab4c8ccab0968d74d66d9c9561650eb98c088d87766440fc9967e8463febcd12ed07f7e44fef47cabf05274002d0014c4e31f230a41171868db68bf5a83c902724397ed181dd8c6768a898e0c78f6aeb886df95442e99 +CT: f798de4998683da7fa9ca030a23dbc493f36c48bb52cd1113c3ea97ef2b67433c00195000777fa3b75a3f689a66b148159524a1fe9576587948760b279cda56164a23748564ec66ea51368ba2a900c97169eb33cf1e557f46100193575737dba670175035f0d921675d45415c6591cae079698e6b1f74e82d4b9216c20e907b148a1d514b2cf653d2e4994f7f668dcfe88dc49c29c544de96d8dd0 +TAG: 3663fb2672223154981b4c580ed3d2d9 + +KEY: a65b520a2ab67a24fb8fc669c41f2753 +NONCE: 3bd6c7e8d29242abecc4c108 +IN: 9d1559d283f7a38847088116f2156b19a8feab0731f04d0d499c6b0d21b8563a89a9c284230c1298b28a622cbdd38dbceb098ab896a7259caaabfcc7b0d9ea797178c18aaaa351c7f516342dcb9d3e91405882c8faa9a28f7c67f3db8913b31c0dcd56472d8ebbfb20cda2896a66bff2706b12ae0d9bc8c6c123c02f1f0bbaa418c1806482423eac72d718cad0dbccd208eb81663a9d9043d6ae7a52cf32b1fa +AD: 2538529cc6eec03f70df2ab085027ce015279484981422f31e58aeee31e79703d72752af2b8822dce9b385f1530f19e692e00e20ef973d333f4bd585ecf122bd4ed9b0626cef46baff0302c71411d27e372361f36c7245096faff21f0236f3dd675646760d5687b3cf1544dbcaa863f1267bce04bca976616b890c7c6ff3448d16072c3938f9b62377609950ff7818cbdd21fba2560bf1954a93517962181b18 +CT: c3194fbb5c319a94c0f61c432a730ce7611a005cfc78266ac4e5d7c95351e71d613f06f52d9d008b9d886f4d9a57bcc232d47e0c75ab755dfccc057a9c7558d7fb696a8c29843a8b9199e2406d23cd6507d35a872fa54cb95e2cb9af45405ebc6b6ee353e8a80debc393329bb9499c61c6344a6380c118f30fcd76376a9765517652e1b21ecafa63c0d19c1875658f1eda89c15ac2daf1a6f526ca72ee792a4f +TAG: fc16cd532c926ba01e2e6b15327bfb3a + +KEY: 84215d2c8f86e5b7bf93cb0620da6bb7 +NONCE: b35e99ce89dffd1ec616ed92 +IN: dfe500919f97713f6d9c4f53913175b162b8b7587d85d5b63f0cd5f51def23119e2e02c224142ecfba7f0a519aaea3c28be20b9c2a9c98eb145afd4db523b7f0b822e67dad630846b2a192bb146dcbeae00198c81b80c290d881125c24a6b01ec901b8912bad5b081ec7d97d6997b33052ec287f692489df928ce36cba1e3d6a41cf10c697a9e1f4aaf75dc5be054b98965ec3ce173be7e127c4c5387048ae6ab5a8d247f3 +AD: 6bf6222e64a46c90f83f47305554d090bc8d3838b7a856f0e5e1d92c4e7231eda6af1d9eb7ff6ce914f2256a3b0c853453b9bc75e46109cf8d7e8a9dca224e022d3d1a139d00476775622799541edf9d53eb645a40f6d98ea559e181d96e4df0141e51fe067542300581c0424f534d2c2e3b1b27153c0cd496a1c03301226beeed2b5cce0710d1f485e68b44a918b63fd8db610c7ff894514e272b6ed7ae33a38907e0698b +CT: 6c6faa54df62ba5659d45f64a5f014684138c93bf152da8a495e9d067b13a30b9fb84847f56231b2da4d87e6cd509a3e38a9ff47589c627e5b5a1196e27fc7afaa14a8432c2d10d8fbfd5d6d394e4b947c456420708a76c2aa638df7de119c160636fc8dfba32227c5de12e5ef429da933ab04e77b489f2eb761d0c753738647ad6793cad64b8942f621ac67b13bd0cab106ffeff21f24c79de69424e50ae550f2241d4029 +TAG: 202b232472d050b9bbc68b59a0c02040 + +KEY: 7c02b6bc3db61e23736c5f36faddd942 +NONCE: b958decc680d5f79ea7b8632 +IN: 7e5992ed0474f4224b8da1d038eeb78413fc2f9614fab7120043e75986a4bf1114a80703780a149fcc8dfd115b768f45917065c85176a3f00be40b427fe3765d3919a5b741708624e29bcae876d251fd46dd8d36a8ef66f671c25f984761cf7f75f4329de7093937cdabe32f130b77531ab1aa0a1bc38fbe2758c2664eded828b2589fc5c34d9a0d57a5a4463163736f419b65f0543f50207fff4cf1065a551bc00ffe9466538b673b2a +AD: 76e430fce1a7d8340104e6001f1c2048d457ac335c5453e48727244b75c3c4f04f55afbb5ce55ba6f8632dbc168ed715b83968a32e5b8e91cb24abc9efee6dcb7a8bed9394a546f0b9efc5823ecaa192df061eb41c671bd863498c2130f322074a711ee43791a1cc02b5cacccf25119ecdd99233abf3b131c83ddb8c62c93a0d653e91499e7481303adc8dbac615ec464eb8640ea138f6236b0ee31cea060f97ea9145a22d15e28eaf6b +CT: 14cfd190ae0521f94ee6b36bfcc403139782bfac3d33fe95c81f53e83c7d0c9a8fdebbddd79746b550a383ece1b5c93316b2fdf5aa36b4e97f739f78ccd2de9963ee7fb4d77b581cf676bb679b2dc4a48d977b45564f21181dc60ecee84d736f2324196c20327495d18973660ccb5dae69b79853d12e48ee0706c8ed821b7f722e46f35c8dee2b7b55ebee01dd3ea1e8ef80493cab6b27c264a67596cee06c15062e3a96b140d0d9ba38 +TAG: b6c47410e6f4a2f2b172c6a4490732f8 + +KEY: 1f58ccb33649d0dc91c50f2aedc95cbc +NONCE: b3a392b1fff0157e95f82a44 +IN: 738e04dc5a8188d775262c2cdaa04468844755dc912a4edf9db308efb3c229b8e46b2b34aee2c6330219bcd29d3493e3cead142cef5f192b043502b8a4cf0419f9b3f5e001a640541c84141e36d585b05a2f702356bd39bda518c42b461564326969983d22c3ac5a2aa214807ede803d57a61c9547505dd7e08402cc43e6ed1574a48366cf5b5573afcc7aa3c4d4721b362d20a58cbf251315f2b5f9e2c97c5ef6bff44beaa5004e5b7c7f28295df2 +AD: 93f7f5054605edc769efc30b35018ee6c929a83bc6454352c69ba9c72e4b4ea6f51c9ed06f314b5682be6a701c719087765d0a7022e5c9d495f28a9053bd435b8b834045c3670856149b08dae742b372a15a0184375d50eb09877bf94f63859e64228606791c516e76c5695a4e529b9dc5f76eff1d4641a22597e4460aea4eff107348077d4ed2d6262744b0a2d6610f25264d905133309ace10bb52f7138674c25e5d43ededbd87c13dc8fd9d3b1b +CT: a002b47b18d1febaf64842fe9011484d618a2e855c4efcccc7d08f02dc9b53d0bd4fc8013e01e21fbf2d9bc7fdda69e68be0c06d32003d045dca6bd251c0bb8c2cbe3693b252265c8694295772b767f83661ecefd57353f6f1c442f9d21ed98c55cbe1db8171ef7b54fe3e3a1a253b4dd48416b5fbc7c18d73692e9fc90dc75d4b88de1fa47c9ad33ddfa4e582d3fc61ca2a8b1eab898b9992c8e56d170730454ca50cd4f28d2759388cb8e302be10 +TAG: ac502a9a52fb3a68a7e90dc639c7ad42 + +KEY: c67510714f556ea1744af9207917eb60 +NONCE: 71b347a21653cec3d113087a +IN: 7040fde3513cf7f1886d7be9c0f371a3b75415e94c3bdfbef485081199bec4494beeee76dcea05b6601ebd4c8fe231fa16d3b0f046eb3e9c9ed8baef25bb0ff6bc85469b2eb41b929fe904735f819b241b01230c68c0b61577899426bf0dd30e085cccb4ac290244d8c1cd7514412a3ebc51aecb6bb4be1a5a4a8d2ff3fc99191f7d7d0b44fe2cc4ec34deccf901f54e3dbe19d2dfe663855fa9d93a01ab14faed7f00c14834f63e1d153441c6fabb3cf22506e8 +AD: 6d28b410c788dba025c387f5b94c0bc392c69ef646b9cdce53dc169326359de26a721703d9a7c5017631a469da13b2d9ad9115de7d06922ed6f093792ac25ae2e27993ad6be5217dc4f6c51e18f230d4eabb01a474704b71b1407d9cff921bd98e28bb60c4fc019b4d609667c747e83eef779ee62000b6800ba2666f415dccb12d43af4f585d3185d66ba2ecf0b0fcddf762445dd1b6154591dd069f03977243b45b113b6f9b110f9fdd96f0b74e2c9843a45c6a +CT: f2a2cdb4f890241f44e00b3373769542cc3dd24c3d07502ed162dfa10be9906871051b991f36b2d5c4240df483c2ad704be14b9efe79ca704e8eeb9dc250e75a92ebf5800c59fb9a6a32228fa1121d21e0b423b77e20010d36b9e6c68dbc000f69bddbd521a1f7bbc9d7e431e4e46e5094be96a928c6729293d2d805c468a3993fb7439f192b1142272a78585e3b7fcedd2f7cced52ab2bc42e2521603b89ba7633fa3b4d07d9a314d1159d7bd5b2dc5198b0c34 +TAG: 0b386c3a58ad23e9a45f00ae107d319c + +KEY: 171d25e195bae2eaf666993f3b42d690 +NONCE: fc16bde0c69d5c894642f1f3 +IN: 8775d6aa2e46ffea6ad4439000a968bcd4fce86535b7265684071a498e0bfb37646f56fad79e0fdc4d6016fd1e935dac5ad74b11c69f5261c3321efdb9cf03f9b7ec681a7f708ba8e3f66648b24c41485a5147df31385809c800155d0d4bbf41d248453302c3754eed4909b267893309ba5249588cb4a4a14b4a29496f1e799559ac9f4baba7a9b4cb5bace1c11dc0e7ef7a2ddd2596c29cdaa378b97c7d3c50db49bcadb8e1840c6b9fa12ad88c0b8152fd753efb04ead427 +AD: ebb169a863dd05cffb9deb866bdd130a1c6852046881f3f8e9013158c83bfcbaa98743957ed4b0619eb88d7ff69b3a5d06da74076c3cc2dff83dc0375236d363c0e2b1fb60c9cf10ecc0fec94757b1b719abc7066af15ff9b66788b38083f766d67005369319967995407ea20339ba27e7bf1dc263fdd54ddd8088232a500f605ba825fedfed69cccca75c207b06594d1d0070ed12a259d4f574f352d2e2ea6fa45199213b6a42d53a7c717250715e0404f2fe7b64e3ec7e89 +CT: 8694eac2bb3968303f795bf0118e43c132c9dd22ec320ecffefbe878ebe6b1e0833d19515c07ebc83f12cd9bb50d2658e6d7fe44a9fbcc2225e93ed58e1bebd78edecbe6c8b3491eedfdcc957cc8ddc95d8116d50cc50b1999ac420802605cc652134ce51a41533e00fe232344e805df146a952b40ce27a2f5c6bbba2154489ca40cbb617476ce6ceac1a6b9c0175ee33615f252377f52583e970f77795b573610baf5cbf5edc6d2837244f88bc155f71588c9c4c1c802be9c +TAG: f6725998336b3ef020b99818e0d932ac + +KEY: f7db0fd345ca6ca82ec8624950f8e672 +NONCE: 3e7ee1a209b1a191f0a00370 +IN: fa86869e14df0fd8e77eba7fe5a933fd1bc58654deab310a03aa7202a089713e323a323f4932b4b8f6b40982d6738aef48951f621aeb82a747d290d93d1eb5bdec6a62fe66774209a4aea7261acff80af9512af090e0eb0f5905ce8baf2a0ec50ed89906d8d67f370639e6f16eafbdfa982897cd5a3f88929d7f1032a8b3355223bf666be94ba9945fb5cafe655d59af69829ef92365f54ff3eebc45e01ffc439b16e23ce892ba6db7e661fc3676a175a8ede746000ca147db57a14303a1 +AD: f7b826afe62356f985e8e10ff356dc9b5b9d9df24486523c3bab7db355c84ec7e4bbdf66482b74fc6b4c6aaeccd7717fba44eb4820a40f03639076776719ea7aabd3a815c201146428bf4c6bf1e8b056b5a22ebcb214fbba64de54089a20ababda5c860ec301f36e1801fc55fe8fa189f35722a2cbf83ae921a9537be2b4f060d918af9b12f9111909d59db7cad24418896ce49762223d8a20a3a83fdf24b64703c19c78f528daecaa8689f307da7fe0befa1d6b1bef24ac8d9f5f12b6c1 +CT: acdacc648833698eff4d42a5dc0b123cdf6f2985ef05e6f2d42c9cd04663635d240648da18dce158b21cc0a3f7a2c35441799a4f1f5622e11051c874b2bcc64314bf0b94c2589d2a24d996af57d22085a64f10135322cb68428fbb951d8b14683bf6fc96b1395829a0b05ec83eeb20e54daf7a413e070ae1e0b73bde56faac630363fe215f1883cd9eef9c3b7d076bbb56f6f5ffcce0d31570f79be8864482b6b3666424dadb674f873a1b52ae6e3d8ec8984edf54186e38c71602098308 +TAG: 4dba5b1385565427a987c9d0b030f4b2 + +KEY: ca80ac4cf4057182d06d65dcdc09763a +NONCE: 63cdd8090e041baa9dca5bec +IN: 701c739ba0c146983b9e1fe0a9723850caeb818514860c3d4adef10dc5e020a8dd7f2fa282896170f9039d5b3fa629dbee3bcb81db44d0d68f9522477619269a59ec1a9ed399d4902f25271dff5c42f3747ab0f4b61c26a2c1bfe1c0fed02282fc2ef88b47825cdfb11df3ced0fe0227e8264132dd62af2d31f23d0c0e253f01c80400127c37806762eb28bc71f31807229172c78ae994b4ad800d6247ea12d3f4f902bb50b72c132902dd4faee05e67836facc7001c8f58475366668ed20d4899aec4 +AD: 0e91b38fdc70951b97e43aa9ea2c6f78d445d90ddf4faabd3e6e0ef74f528fbd5c3d4da18cc3d8bd3167b756da495cba49ea35e2db849bc37f6db8370b492d7f82f2efafa5444ac62835cb5602796cdbe85caa50084e51eec2651996d2da0dc18fe10bd6f374168d4c9ea0a36ba665148192252ce9d05cb78429c55256fbb65f1bbffb8799d63bf41701d1d706a44e3f27eb245cf720f2a329ea24fbea803c575513830fff579a1bde3daa975eecdb8d3956ddd374fe252637aac86ed3c702c4ec63e6 +CT: ca46eac0addd544bb45a97a4989d45d21599ec70f843d9db38157d186716dc39a5d1a5c0624e6c825b5b7f1fd41aa542ac846ec0edfe6bc28f727823667a33cf6cb5ba1ba6654cd023857c53ff00a63b34d2c17ebae5d46dbd073edb7b2f9e02842dbf663bbe36238f3eaeb7a23e328b0d3d50f49674253898f360c0243722af266c934f021e4f2fb8747fae728d06717b2d68cadbff762956826c910cc8ad2d4aea4518d5ac4deec978a13072fd1675a272539ebea31d736c759227f31abc911e0e76 +TAG: 9f0202c228ec48f4be6b2f876fd05a83 + +KEY: 9c2daabcfae974ae165a2ea58ecb212a +NONCE: 4b9317e4be2256a467e2831c +IN: 09169c1f5d873f03821393bef013bbcafcd82314cc986675922e2d43031417c8e65e625ce737af4621aabea6fe75030b84acf96967e791f8427b8f052051d6247a897006c6ddedd49cb7148afa5109a561e78abff7c55b97091f356e31b5667270d5653a497e2503d75e5856ac1efdcf3fb6e80b8deba8802acc064905e2b09d45e446d7d810971e5996540ee9c01fac1b4331f99ad329565a8db38eb93f2e2a8ca37d64d73cc8a7f4fe3234cc155226393f1f2ad17d0f01d5e60537ea44835dea853e027dd597f7 +AD: 1feb0ca13b3022456a4801d8f5382cad95f7a50e466a102d2208e7482dc8ba5c710d1721de7103000fe8811bb13fdf698844257dd164f1e21b0707251f228ca8bd437994526ed5684c4165c9754d1cefe7eb18f9e116a455c28db1f7c04feab74ab06af029819f51ed96f453fb6a634f73ba8c80e19dc62384e82feac70a12d42e3125c360ec2a97f4ce0a07039687ffc37c5dc1df1ed24f05a37591fcd5c34a3fc5f825c79213adbbdef65078f5e41a4062517334a67560ab215fedde53cd8129a51f27baa80f53 +CT: 8a4d4ae0842f8032d83b2e4eecfaea439f745f1d0d07808bee4b68e3b58fcb65a4c8fd9b93cba2d5b4781d28a9cc01508e9e85796551064867551f9083cce342ba1aac4d2b8f5b0b0e4e3d7c82082c441467e47aa2b0f47e167b28fd29cb8d5ee52c2298c1f87cf811061d922f056214346c1ec3d2534045c5c485ccddac7d9998d3d08a80a62eceb2ee18e1a27f97616969df52ec486015974f160745667d6be25ffc20b143d89bcc8b6eab9dff82ce3c8f95a034316a8f2f2a52674105f1246b2daa28edfd829d +TAG: 0361e65b1fdb9d967492ded32e1fe811 + +KEY: c98ed84949749efd2ee41eaeec51edba +NONCE: 7b056c9c7b393b0b04382946 +IN: 41b87fe62c82bd34cbdc70033ca8d2ec5f13eb2c14947f97fbb5d97da7323f8eb5c2eba210be11b1ab9554feaa516aa493822af4a264c8849e9c6ff41f690f44966bb49c9c1df5995de8070a2fcfa42d0b0b5115a36738102134f571988ba4fb210edc3202d3c74b5f8801a7d1e217b90caa27acb49ece590ebe6637fb6e2f5f0b849f29804efdeb8c102b3e3d2abfc4f6f2c5f71f0a6e4d5daa5cf16561914f14601edc40547d55f7d11eb4768d5c64fc621d04e8c64aa3aa1245c7192852d2ccaaabd448e06f806eae66da1b +AD: 2fdac5a70356c2c8d70def497321c6bee8ebb08a5abc8dd508d83f03bf1a09942d7f7a387d4f875a1ff16c7b5abb53d32bcc372012eab7a3b848a93f7af634eff8c5deb3269d418be698a3026f6f08f55a6e31543105cf1ccf56193cd1af802f32e10512a6bcd3101b7b54a8f3efdba03018d5f2475b51bd65e5e183a62ab11c9462450883e3e87a9640eac909f72b83da8bbd34431ed87d14c6f7e79957067c1cf2a12b5fa083496f903269a3c6c8ccd5e3f9cc287904223ee62bffc4f157f0db409e82101e3ca5e05d962378 +CT: 384ddc8e7ed6868aa722f6785fab15eb69caadf43246521b97c8d016afd976360365bbfc9f48c08b0eaf5437af8a9c23061dcbdd0d22e1d58c92951b43e013689afa6b1587f79fe9ad3104ee1f80b3c95388e35b0b9a5a3b733b32a3e62fc143e6255d0e5b1b55bc9439d3c1cbed610d36c3667378bbc1ac20d93a5a7e5563409a5b94ec799a5281213d724e46f4987588e6bc7e9e6468bbcf340d5f1a1eb1b45dc9fe9c832befff54c8a85db9c07196d7d45cc389fc9d62f4bf1f4bb82801cfa9c408498331eef4ae1ee2809e +TAG: e8cbdc1d6d51ac64f16cf08725f81370 + +KEY: 42ece9aeffc9d2e8ea02e73d1a4de834 +NONCE: b59e0770c689d60823c06c69 +IN: eccbb9a2c1241c88d17204cb0f0c069e20512bb1d31f966349add203d84cbb79d88f7add957a0a8370b9a0e04c9f17215531cd48d08c4612bbeeecf3dce68d41724166e06a331e7897e8c7c6a6affb7bf07dae1874bf3bec044d38227bef5c228f4cface9ea37255e15d6b27e154b349b16048b0e7984f17cffa03da07924b190f9b91d6222db1124c1e4e77c2b989fe2a7c338c7316a49c7df0be173d0420e8790bad669f6da96745cf34cd2eb429d18eeb61a8e80a5e03294dcf3a5886bd1865e2a55a72574db8db04a9560f969711aa7a +AD: 2aeb8ee162a7aafe5a72a8d8873ce3bc43a65fd7bbdef1f6ba71b61e5a9c3bd033e7e8eaa55e08ae381362ad0991d65bf22c99a425019c4cd7768622f108f5917a4be22b4ab65ede66c58191e402f8cdad69decf6552dd52b62e8d62268b84122b64145c97115373a26d2d5e59e69b7dca5f96c48106e9fb3f7fc7e0ab11c78a1fafc697fc73603d3f08fdfc0ee885f84572fb04fda718a21744c7e5dbace91b0e141fa82fbd4d1a7dc35edafaba7c5894778c5952ec787bb547a37e509b035c684a8f51ceac5e12ae71b165dfe957c6de15 +CT: c5874137f5e75ef02521b37f0759b5724798aaab8a1e62df81b73175690ca1d32cab6e7a9d7803a8aea420ab273fb46eab9e5f0773b7f5457d7a8c0058ed9675a6e1a7f15805c7fb695d277ba06adc3963606ead0cedb342614cb410f4197f4fad0b5df2187f8d2ebfe85ad3d5f59bbf652364c7e8c3542c5d7f15bc6e6c24eeb1d3232bcddf6588ab1c1953085bd0a1516046b76714d2b97718ce57ad23cd213507f6cda95ee9c5c23036cc7d4133c84a1d36393979f9d1bbc613350252a6de78d905607adf51368175a20106f81aa9ff9d +TAG: eab1c7790a5941270f2ae49895b3113d + +KEY: 6ace8b5fa16054558c9d0e272573a7a1 +NONCE: 358c73828e032f0e0db608fa +IN: 915466e994705239afebb8025aa965626973e41a750bd75f9e8ccc7c1078ec555fa618120b4f4b5e273fb9b262df73d39950fe5cc1c265c06a08e2318efa83c63dfc689de80966f45cab0d2dba603bf116b9ef7242bf4d9cc691a775f78148d2c75059d6049c861da5dc40d5f94848c7247a724db956d050975d613433066ab89bf91936e0fc85c61af5c2c61cd1eb414b9df0dc125a31a3805903a886b427fb78551bc696610833a9e55c7776ec1622abf839d733594864de06999be8d483f8dbc4da99f541c6f7e21d946cce229a104a57e4b823bfea +AD: e54b90d037c375238f4989910d423bc58d32ccc06ddee558dc6a0c2f9a0f13b2332883e2c4ef9cce41d72cd636516b3506f28f914dcc88311fd7c79bff0ad32770e4847362affd98ad468117cf0daa0f5747c86359615ad6087ee18e6c58453be60f3bf30f8c61c1466d107116f88499fb1b5df9a01eb762317676d5413b839c66e5c1b74121f6f2f7408825745fafa2b10ba7450f4ce207a9cc682d1e1442f972a86d5d4039c4856ccbc00c43b5b3412f5b3f87c16508ffa527c8080a556944d359f388f787f9cbc033fb3333e72127e94c455b433222 +CT: 37be446820f5635c1b5ca1d8ccc2c5ab5b393243ef5229999a2c084fbb54a330bb338963740ba470973adc86e640fcc167a88bb940e5ad1723a01089b5e804b932138efed6fa0ed99c1ac4e9c607f466c829af04407a4a2e5cba486685f693a7b973921746902ad8a0242e02075cab66204084e6b281d58430f2d62bf55ad56ad279bdab0fc8c3d570fc3371dc3280ef3aea70d686c855d40ff205c04d457adb518d904f5715fc6a9a5f30bf1cc74703b175d70a1470cc810a366cb8927fb937aecc200928db6b73873935c429e2f8d595b418c5b1bf9c +TAG: 01b05fbaa9f2257b3c23ed3cf91bcbd0 + +KEY: c5bf40aa1127073b03c114b10f3f78f2 +NONCE: b4ac4fe9920fbb4e032f6aa6 +IN: 164906110c34354a0d4cb6370e1ccc17a739350cbb11d6570f398d50efe3d9db1a97f00d031a579f56d23da2441295af18a640a4e33c29dfdc848d722786d9b73550bfb76da1676af24a7bdf5fd3301090bf342369a24ba830c7f8883db6ed77a2ced83bb85205ca31f75a16a58fbbbd163a3af5e5021bee2d2cece33c08442e89d3f4d6d2359b94a7ec6cac388208a689b584d5dd1103fcf6af10ea2c7cda4f690ea0e4c7376fe2c3e69365d982da28c5bc18d58fe384c9ad2689f4047f9575e54970961a02419d9f2bac8061ce943f132edae1b9622738593cde52 +AD: 9f05d0391cb128690cd8bd120120f21725a79e5d2d0ef9e8322c04bf775f7215a82ce1ffdcf0f6562c188e84cb520f30842b8dcbdec36436725633325020cfdda7ed1af3323d86b2bc72d1b4a326f02be2231fcf133762c4fa76c8a7d5d3ac31cd19f63411a220eba4fcbdec40b8eb01e4ef33c6620978d09a8d428ce0e74d02c140881f46f6f81c2850edd82dc46f3460b5d5fe0b54f09a3f31548dc520f1dd46ed657995e63297b6834df57525408b944badf56234eb2b9a43b1422a5c6a59bc58be683e47753803f7341cbb0075b5795228b586cc571c1bca70d5 +CT: 5c75ee10a917651c49eab6a1187ed631c7069134e492bdb5e5698f8ccd5503cea5b1902d779c2f6e6c03b0108cee3fba03f2b47803e390930060ee4ac984b1ceb9488b4cce80e329d3427851aa7da2213eca2dc5f79366caf601c49a6b7a8ab068f1a9bb899b81a23c99a9de20466fe01398bc071c724b2942640cb1a00489e0ca7052f7a06398ad42500780f194078e3e77142df5710ae88540761b902084f57d87c2b0ec57bcb7eacee6743d419d8877d61666f93a127d22ccb49b5db0b93e4f4ac0dd9393d6351780dafa412380205a90fc8daad3dfcb1b7ffaff +TAG: 8048088e7e9dadc4ef98777c0f6cb661 + +KEY: b628ee6726a4d7925734ab1db3ec4645 +NONCE: c830b0d1b4113f4c9aae46b2 +IN: cdccda3718f2b0963414d965a3c36bce0a165f8e88aa70ca9eb3de6510d02b0b49c29cda4a7f6d439c18cc8fd80b932d0a4190236a13edc9994b1c4a71dbdb694ea5dea53ef781ed398e453ce372a99c204a138739edf5b606160e38cc8444c8fb6e9cfc3aeecc1760e90d13d01692ca894572a0bcb02e13f61d8604a75bb98e96f5f36d10e70a48bbb4f73771ef97031c7da23550b3a12554c2c436115fe56713dd303d1c3d87bcebf25f61710eecc9f01c555494facac496c68ef44344aae40bbe1199de793096d4630018a725b130a27d38ab2e8c629e61d2d8d37b5974f9b7 +AD: f4d345e55ebd1ef9faf967d76736f7ef38e5eb9d659bf8a89fd3c6c3c674161bb54758f1c14856281a7dff7c9cec16cc138384f644544881d50c7692bf22513223b63274e3cb7509c8a410a389277f86cefc801d026b0049c13d85b26da1dbcc7cb387084a3d4a469788ef85b6da02ed2ba0412ba999c8cd83c9c6716cd66b65760c42d4ef3e324b470c2a5e031846fde97cadc448e87bec15164da006c10d3a846adab2b09c29ecc27ec8a9134d5fcfd2c54f17fb23f1a05dc8da46e737f317db42e927818ed00d36af8dabfef09c8641159fabfcfaed344b03a1dd6f9b883f7e +CT: 4f39b8fbd8ecbc8aaea871db2e67583a5b06cb83ed8035ff639dbc9af92c4e3f9fe57b970f4e998a0262dbf77dc024d5e208d3678ae0d90e6fa5d45e2c7f0cf90676368c8784c851d3818e221abaa87c5e54298229a2f4d3f82505ef7bf45686aaf12e8322210a727cfd57c74a5f23bb5d8222115b28503eae7a5c600ebc4765011161736a346b535e1bfcded85c198c6ce6fccfcff0fdb0c2fc480bc6e71fd5de77355932d82f8eae245091bcf5abfa0d62123302e5805ab1f5006a976bc1468e3bed0452c5844029d7d4ea6cbd4a907e905dfc796c01bbeb69c54807354a5bd8 +TAG: 2b55edb998ac9971e53ebc8973c4e8fc + +KEY: 095b26bf096971842fae34af6833c77c +NONCE: d59d30bd5384b86b19b33c13 +IN: 3be9eeac265ec4eb947dd32583ac2e595505b363d660f8b8c2ef631390bb152f016ba7c75bf7c2e5e23c980d6967772ca4535bcbf4871ac1bf70b53826a34174e5a2e6118d7ff86d4836736c9a1f9de44c80b236c5530bb5f80e5fbce9814f3b0843a088afd029f4cd2e6190dd51fa804f8216448e7acc785ddc5478287b101bab80256977494fae87d0c13054fa4470c3827b2e8172224944c8c4f78b0a33dd78ee2bff16fabff15e5909f62c49beb455dd655ee1188b8eff35bfba72f2ec5e4ebad63d7db8b6338660f9b818c6832954241860925ea9b7eb07479dd6de27489d64b1a9191b +AD: 2ff9a8d12980e63a378d6d635d319c26e8f747435aa5d797c6e21aa69fe21f653f56da7db7d67cbf54451f336f683aa9cf373ab40c16738c44efd3e664ecc6eec40d6af82df2b3e58d7abcf26b1d9ebbe6263176ce4ef8087d14b0d5ae1c16917141d2ebdc76a0834e8d83c4ef76add82e957ae376b210ce2d94d2684a045a109454799f3cb453279d89c60ba9d038a1dcb99540fac078d7216ee94f96f5cce939eca9b5f9715b1cf3c9f1e6be982897c2f25225919db3e31595713a4e281e9919bc2c5a88c46835ce05411d0757eb738ac9e45ab3f1a42ffcd6dbd09f17f656f40f1cc2c050 +CT: 4723fb7339048f811434eaaf1db24759fc232466f5f53926b84e740b67f457c8c76f902f4d70ebfd97696380de95e8e40e62434ab1089e3a5308cb066fd4cc7e862a391c2f727a63a01bfd9fdb8ceae55067fd9d6f55312f73bc2c38e4b12b3aa96edd156dd758e9175e67a64a17aedd27c9c70945a065216773d756f533b035f2ab53335a159d9ed3f97b2b7a57aef676fad95c46e3b82eb800197c03812ca4e580916c5f7cdbd4aa1308ab16096a8af5290a0a2330902966a58dcf2e72eea7ce799a8f05c986c6457b05e3eec2adfdd4ed38926a3dc07ef208c91a619848917b96a082ac27 +TAG: 3ff349a628f7fa8d3f970aff8a6302f0 + +KEY: e27171ed1baad563d3d299abc0968b75 +NONCE: 5931a4414d5a90e93d2ac47b +IN: 1d209b32a772e87c5bc593fe943d3d7a1497f390ecdccfefac50ce14595b98b682111f82957278241f291e655b3af108a9cc1523721652b6d446f34cdba2e61464a3217b29344e18ce8f47f10da88c2845a009b7491bbd1e1f36ec49997a0fb09764ee25355de29e56eae7af42a8c96aa137c02268078b7f145fb1249bdd74f2d4e4685de75be4dd7fcf29482eb26b5dfa5028accbd23c3c654bc202c1c0ae7a597ef15f4d14f7b8a14fd45698470ac6355e04fe4a14e3b2907bcade18e4152c68631f313cbef48341008482f434c017bf8e1dbd048f0d6d207446e697fea68202be7283188d1227f21ae4 +AD: af2f6abc40ca82d92901de02113cb8f7638f0a510f6a03bf056a75b02beb10157c97632320fe14fdf0610235e3a06172b6b6e80d2fe18263b11e9a5e3a07758c55131ffca0a6c9b121c37a0c85658125d5bc2edc8e4e247a636d7793a1cde364ac22bf754844607daec0a6b939d05fff5a8c44ad030181aad2361ff61f20a224f2bbf2083b2fc2a5b92f5a66bf2f9b4c49b39dcc23cd3ba66b5e7c19c5b7b74a766c3da0c2b02ac80ac22c006e8eaddf48ce6f6887f69fff1fd0aaba0a0f70ef84b54280830a62d8b0dba55ddaa5b0385c586dee60d1a05a28863a081cb9b41edbf3ee9ebff98cff983917 +CT: 673ae48b6080a3dbd08034312c36201d18508f4e1ee178ae2632a9a5ce0938687ac7e6cb238cff852ecfc736bb8b3c04b42752fe65cbf6ff897e207582e85533f7c238b0be14bb1deb4cdaff524b013661e4f2c96807bcd928e15e4e159390e1eeed036ce776b579d9f3fadcad81adfcbb99986babc9a8465def3de8de0cae19bdbf6488c12534a9b6b7d6fdaeb1d4c3be36b4adf7444a0b9fc69c69a46f7bdeced1214743f3357803d2eae24dc50933a733defc653dec56f0e0bfb8928de76699d4f7029fce9175b3b7cfb6c7ab1018f6f3eeb2b9401115c8cd382b06e4b9b43a097f42bebcc1493a49d4 +TAG: 285c1a0028fed3ab2a4d68946399d700 + +KEY: cfea8c059d7b866051aa54b8977befe3 +NONCE: e54e684ef16a2fa8e25786d9 +IN: 5a20333c4dd9b7378bfb773b7d64ab80379d16c0a56eb1f48f53c19d0fc4519d0b5f478e37f16d6e5085af31dc63488f9f2cbde3e49ba954b674b0a4e20df811098f7b8e716efaee6a4109f16afe128ddb0e54034d66bd00d13a6c69c9ef2e5a065825701f5e85634e118c69ff0fd71bfccc25030fe94e778e7f474136cd3722eb5bfd88bc99fb45dbc3060a24ac2bdadc5c82d883c5c63ccc0f7aaf5384f4c7fb07310b66a7c767d025c1a02dc9aa3d7aa921a72084906ae6039f837454493aac3e3549ad3722a735dfce4211819a2d7ec279221d43360edd9a4cb930815c8565c22b94b4849a979d5e2a57b2da8ecb +AD: 376d8e02071a93c892293902e369b8c7c44a4c9541b5050347b016243935408d0c9557b0f66c6cd493c1b8da68c8635f4c868e685674aed42f196ee9b6e56ee44510eb9b9e89108d878be917454dca0c62d207fa462a563a267270d6b1602d6795717475bc6fb5c87b747589328e39b1d4db3cb19f0fbe9791aa4232e33abd9e14b5fa3abe4705ee988c657677fa063aa349f1a05de045f3ee66da03af18b6b8b83e29b203e12bb02a4cbaf79eab3cfeb83a5a997daaf8f36fa9e12faee86c9cb351ff361351d98ee3a10af999799955a02fc46ddf56c23070319b3fe0cb42d07d811ae976f242670e618eed113b4342 +CT: 06ccc7336773919c2b1bd832e7c48ae4a569db96545363ae0b28061fede28a25ab6cc0382aae3e6b31efaa4c225073640d0148878524a7f381f53b4d21a43e39afd4c12cfdcda442d5023a8d2a8ad49f4a002ecc8354c86520524017e561fe891b6962682d168a860210e0def1cb4be1bfc6590121c1b1988254757fc5a37ef916827a5fc258ae772773a6902b084817f3641c21d3d1d1e8818b9851dd05aa49ea74e16778593f6f486957345462732ab92b1e4b06c32b5ad3270c5ef3d80b4e4bd08451e92c26acebcac1a4592e08ea434a1fbc6dfedc677151ae9471661913db19723184d9ef4bb49342606f784d98 +TAG: e7be877dad60c889d397726bf1b6ea89 + +KEY: 40d35704108a944f1e7582503018cc85 +NONCE: 26048431289e7e100481e2bb +IN: 515f9bd4935dc10e77dadd81f5a4e0b53eb858ded393979ed75330b80adb36f6b81288dcbc581e8d93b0e4705c07be3e200422397ca3648c9676952e60ea26d12198add3e33cdc589ee5a800a750d77978976344dd5dc710e56dbad462fab7fbd08c057a9f8765c4caa9418e6380038d288e09a90befeffb1e8d60e79925dcb3772cbb3258b15544f9c9554181df3483784b89b73bb6f9ca55f6d644c02fbd7e31bfbff45cc40132d2bbd08db6a27f5a302e1dce2f0afe4ef5bd4ca844c7900ba18faa1896a36896a1c80307cb37162174205665613b39cabd0a5b2dd1d5f8b6fee948006f0b2e31488c0c613c1d178b7800dddcfc +AD: 9c86692c874fa785e0d9384061bfce8d8332871ecc195621ed478706c46057bb4fff80515ed65b5fbbca3d463a62e227c228a340143bf012233b1c05a50fdb4ed04b840d983f47e00e001844a0d2ce14f6dcea58069c9b0bd8824537d2420147be7caf4a88dc9912853a7fde6d2a5cc21f85eeabca7902b94eb79d5fa143d02585acd57b93e4eb6bcdbe289a51c6631f7aea7bd9dc0f6cc2ee8426b37220216f834033fde15e3543422612fb3d972b8eacaece9614a4b759d93dcdeed026cc90ea058d7dc985c10859d4ef14ac5cb14849d4ae404badbcd98c28663eaf7274aade4bb7527c4f960875ca703ee6732c9a3720b629f2 +CT: 89a21a1d502ba947ac1921efd3c998bfdb437c2da0802e5eefff66de3af00bde934fb9109e961f179771c52de783680683f4bb752f877897882103146d030bea5bc3c03f923b477443e640450244cdf66d7d346954f6e862a3a577820d49151a82f4205340ccf2e11e4575b53f7ffeef09ec640df65a0b8c04b37f6dad7f940cf2d7446a6fc5bc2dc31854c27567b2badf6f8e94294ed5d899a458a080f38d6e72df59f13f5c8f736264fa2b302d5375d6e3f8c3abe4811f4f85cb6e302e2c12a892a1e7a78a5a33e4b555c02917330ea7a45f20cb59fa991f183d1e2a5bb1761005b73fb728124fa2082f41cdbc88bb06389eb165 +TAG: 5476c08e9561442745fd2f222d08b535 + +KEY: 2c6796d0773d12455829a3242ac7d480 +NONCE: b43c0e7842006f6a7953d598 +IN: e0f7ac13e8cdf4da6c17f1221df18b98267277e79c362ec2793dbb842bb9662b5e2fa34e43cea12f71b4eb53d9c862f176efc5d91f06b5c532d9c30206eb4355ad442127d325ae2c30ec436889e3d7a56b683ee09c7d79768d6876ebeb67b5a2cc13df02ab93646386106e0473149ed77ad0ec91dd282712d0aa26f30bfc44f93cad39504356e3472c5bfcbbf9557cd85b53e33e1a88d2f08686955a3d876e4eacfe783e5f6089b3106295899d4a73fbbdc1bd22e1408a2b93a9d89c9489cfe7a9a7cda7c92b06560a189f5ed04d1f02489685c602f8741baeef3fddf610b1a25ed26d88daf9a05aa0a476c8000dbbf798de92b0ab8779add7b7 +AD: 1048769719a44958dbafe1a59a159ddf2427c5dd8746a8454180dbf59f48ff6467d760f8e06aae8d2d2a79efefaef2dd2abf33ba1929073685d0320a583a56e8748288b50c7eac551aa859b274629f3d3cdca5fd7b2a08f0bc830e929584bcba85f80e2eb12bf83de607e4749eaf7631c3545f06ac236d55769c8a08427abce0174c52718c2c08b02afc7e418bd7aa7715de95a930eaf92f54c7dfa2f3ff3691187a21c6bb9b238d2fe2dac7266de30c94c7ee96fa60caf5ec0f5aae5cef28264933cbbc295cade787321f4c12f63ddd85185997a63fec48fc5ddb83be3b47a94e15dda3f315e7495098bc7a0b7d26802e12fdfc6a94bc6c5a76 +CT: 794ba0a7df144e66e6e7fc83ee290431818d149673d1821e1df496565aa7996f9e581fcfe9499c01d8716fd3f6d67acd6641285b70f8457108063933126c95b665e551925722af60aed5343e429e645574a65cb6fd767b204ca8fa91979c6fe49377fe4b43fb9994e619e1dd962fa49a8ae5ae0b8eb630f112c43a4e9c28ad91fee9b5bec0b27c5472e30c2699e984dcd9f984a3eb7a7b7209a165b2f4a74bca555dceb81e3495a3d39115d32609f372d8dfce820aded274ac567112d295de5b261b10c01f4939ac532d4a0591f87742d9502d7a2201178b4cb4c069b1873c44b73a901e299d4a41e57dabdefa39907dc559b44e99f2b950e09c +TAG: ae5afc2bc4096e308cffe8063277ef88 + +KEY: 092e4a78c47bcd0b169aa35343c885f6 +NONCE: adb73023c873661f02bf4ea6 +IN: 0751fac5f54602181fac252cd2fc408ea3763fe229b80149bfb4b0044f541801843c8a20ffa1ec931830bdbde31efa998e0875c09eadaba6906c870549dcc650b865665c56b5cf29b75da63de088fe4d79cce59499518a04a17dce18879e3e33ed11ad808d470b2811da4617039758109f56fe75eeee696ff51c18d5ac04fe895518fe59435ed1f073b56079dec1701999ce0e5ab45829cbb85cb1f94dc67c9ad28815728f6de85fb7ae12203eff28420393c1ae5cf644bfb5633156e9189beb02294d7199e54ca0d2012bee2dcd6322eb90f41b3c6086cf0ac6b3888b21131f3e57643f2ab60141aeb17d9d07daa213658b52503482fabc4a0ba17bbe3a1a +AD: 60fbcd82efaa99e17f3cb16a4d2a1e04659d13d84a83135a5e332366ba5e6716bb3674d27e6b2df4269180a0df25841e2235eed7d8eaba571b34178ac1a1041623138641f500a7d4ceb28efdc0ab45274cf26c0dd16174c77dcdbb79a7980e04d48b35efd3656e501e352b605bdd1b57cb7f9ceca5ca14a3953b2dc77d18fe1c4e1b859d2b02feffd3da7e259fbbf27721d330049f0d1c2729ed2f8048abfdc0e7b3609d2e6b4f5b42ece472f0fc330247880fd04768b678fbe20ba9581f3db18bf3668fa0c80751d78286e1927aa6e27ecce63fe883ee88e7a05f8ca2a387b86246f7d1a4791881b14f619a340163da62f4130b2a2c0bf39f463ef0af4120 +CT: eb0fffeb17e3309d1104c9a9c211bfbd585f9516f775793c365d36352e93af1b4db15430b454d1e7aa913f2af994191c365d76a4d49eda531fa7ce9c49b98bad4d591c868fb066a2e00a6bf4b1bf529002d403313c5df306ae34b8c62e939569bb5401eb7ba87080ba505e5c40a3856d2e177d247a5d8c727b32a13014a00a57e9f01cdeacb4d1abd16f1548256d661c45da12c2fe3ab561375875c7b6e273bbff5659749631fe26cef86e02742d0cc3f63a76ae5ece59b6556ab27da9de1a20c627da8bef3c596ebd7b246505006d1a381c2a24dda70e52b126b919471acfce274b89e07d125bc69bd94f2c65bddb82441897973566014fef625bca7e342f +TAG: 8f2dbbcc01538ccc45436e7176c2df47 + +KEY: ab1405116f454a3b1f106fd491cdfc8e +NONCE: a9e9a06e4bb83c215fc59a00 +IN: f64f0ed5ca25e118f2a2dbf069a9dc0169ab0079d91c6552d4a7e8d0314c910ce0614e1f6157b0f758ed6d3fb3fc3e2eaaa9718ef30e8d0c136c8bd6dcff97c0f5ff8a5d3808d8c23f2a9ccc35fb9427afd10dc1c298e95b335044b8d33e414ecc17d7b34901608284bc175418910116410a40b29dbb379eacf4ead521db3ab2a3d9956081af6d7438714c0631147b7d1e9ee4789751d4260b57630bb573739a3fd0b19a7ee8c301d7f1b09f86e60e31d5f2a86c7a65b244d5e4d591df3df3caab80887ea5f1dbb569516672eee351db5d5ee4d662a3d3c0e48cca108966ac6dfa6e4f9b88e5e577752826d2da05f2677dac7c31774eb64b1b0fc938580a78e4a296889c +AD: 3726f25fea1d10c2712d157e1a1bfa75d6f9e5bda448944ea2b7b85c7d4ff4ac00f68988f2a290cff3d5dfd6af33770a021b03fadd5741bffb7532924f3f2841a7f7658c49c6b915b1dc41ee4bb9ee89386c9911974979f43e71297bcb34ad6ed085177ea91300c9b42524503bbbbfcdcaea03e3f2c939d6b1dfc9c6b6e53e221568d2557bc3055752f4fd487b903a2a0bb7697a19a763fb7c615c7edd099f72e87849f57722cb0987651bfc476a0acfe13d02d6b01f761784d247301bf514a14a990cd4b59664f826649e0f389787641c1e5b87388cff42fec144d6ff3f382b85062bc21368c93019bacb56b643808a848c60bb3d804aa64e2b8fa1c128d6914663d9d3 +CT: bc1c14f1df6ca46e6b4daafb016daa235718fcccfc1ac698a061885c33479c0a7fd44e46e805869383232168940b1a9379bc652c565059ba81b4ec2ab435eb9b91de5bc03cb0a7dc11805690ed9abbadafeab2add15f9fd69b5ff4bf4ab5cdb4a6fd3164ceb7820530641d8460b83929b13860bd2e64b984407dbfd2de51e865d88c63554ea1f04305ab72bfc991fa5573bd6b41c4f8c848fff4b0c5d2398a57b4de4678ca4dfcb16a7612773a24088893444a8ea3d0916e4b460b33657f41d2b04d0c28653ed068a3653975402c31088cd74722d3bc09c50679d0ec94c1e84844886b1a56c4fc3b14614634f08c5b0868d276e9f8f992f94b2c55be5f2e408a498d27c7 +TAG: ee43dba528a9ce84a53ed8fc1fbcd871 + +KEY: 7990cd12d13fbb929fa541bdb8e3107e +NONCE: ff7b2818b62e856952aa2cac +IN: 5ba2afc1da8c18d8be3936a2e515bf9eabb93e44905a86773a38de7f959c49ca56d7f1fb43213cf7fe394b49733b031334729ce6c7ef17d843790fde814672ca982807b76475350210871ddf8309f59fb280a7d41726ba7f00ed2fd96b4a17aeb7d157130cb7e49c8a454cd08622824d20f86b4ba062bb3b3f9d4a9c1402a9d80f3324e4127ee57ad94f87d6ccfda76145363fa70df95341d483dfcc304757da7541a0f148036b2e2dc7f93697d8d275456107a016b425542a89ee33ec02289f5260257176369d990c8c89df73892d7e67227086c0c2c258e5fbfff8bf9129a230c229356fb0935738d2d6fb82992c3465ca5a9472ec06c7b5a29240b611837225c61a0e14ca2dd30f +AD: 865a9b2706eea62f3fd3164805cd8fe4740d1ba7be809cad9fb39cac26f7c57d4c449f4eac03d87f87dcf219c562b9ee07ab3ce22abd46237eef8221049fe499c9189f789948af92bc434b24aa44fff600c2d698593bdfcaea878f8780adbe8dad2cf453d253e8668631a6eb831be01db9c7f1b7b8bfedfae83bcdfef3501cf2b2ea48bcb19f40a70733f3e4c3dd90e17912d5797fa46ec852edcd49b0780bf6287679aaad13a926f750ad7d3ca1ccab577b74fc0ce4cb22e5c619d2d668292c9db4a98c5acc4c49561a77275c06f5c3fd514ed8555db3e2f50dde5c23e84a38129e7a91cec8d168bc828d09239a5c6bbb180bf69950540d8876f9fac5d1a258543a771610991b92ec +CT: 1901c8f9b5a99c46c9cbdf8ace9db03f36ac17183295544d8170fdc3a16c7194a2fda400f8f0b251a3eccf639f539cc356ed3fd09383954a8119b536290865c30a629d44e467acff5fc323d2be97f29fb9b4ef7cf2c18a63dabfefd7f75e696c574372f4a35249897a3387a2b10c1a50ae23ea74560b498c9d06bede78f4c8c9d879667c8c8e137a0a254f3f881ce8d183588546e066314bf1989d1acadbae61f7836fa633de9fd0fcc5b3f72aa03ac432be8f7a14c8e86b45bee416acfdace44b783137e3135a801342061781007ab939a52c68d686f5e3b401240bb10e764211a059fb0aa00e2f635ef214322918fffd0326ae38ee939b4045c6039df7e7def36fdad7f5b65c20dd +TAG: 3e003897b4d9411cbd449cd8dca5b58b + +KEY: 64f0a8065987a4713e35dede10afb708 +NONCE: d6ee984b82f1097331400f38 +IN: 29327f95b41119679b80c3b51fb5240490689880ebb5ff7b59a62ae5e08f7cf0993c09b13fd845ffb32a99ce18c22bb8825c137c3aa622cf3a8390042c6a1a159aa1dcb6b6b21f4e07fada584dd21620b2fe0aef64dc609aac925d8b8d26915fc101031b68a4bc89898bb92146a0a580103da265cad1946791c5735b95d85d3f0f1f39a88f47b9c52e61307627c084d68d14bd14e3572825e190bc7146080bca423099f643d53ee3989386b87fe3dd9c383f6a58fc0437fdb2087b5211df2069bfd981d8ca785384cab31545ecfc35345f38837883dbde917155e631a46ed1444ea0ea8a5441bebd54e5f6ff914fcdd66d62efd223f34e16a880370a529b2ce6ade88e907102021dc87aba9900b6 +AD: c8116196a12363785d4d6fc593b23226a5fe83b00a77ba24c69644d2e52291dc59d2af3c6ae102707439f22c33251a01c41867f54ecc552396a5aa98ffc687e3a88d8d0dcf826645bc78ff9c1a3052481933c3e8ba8e30bc249e6d095699ebdc51684696a15dcc9e28d09cac757e51336f79a0cd5ce8d070579e12956a740666d28ead49c47bae10db20fff8dfe6fb0260a87cc6f5a879cd0b2f949dbff046d90cf42c7ab51337e8908302935e50755a4503107c84fc94f7db3d3f0e8eac9c0def7435676701c9acd7f4c2349c3b7324622dfc4d6ddd8265a810c000158260aa6a7e3af973f8b178959de409792652e9c4ed1d50fce2e5e6bcf205c6889ed717db7f4b14500aa8641b8514150cab +CT: 3e04445e0ba21e8788f6f192b710b466d5d3433463f0308a3c0fbf7f1666fe01853b9d340f496bb0c2212ae3e3d34b0fa1adaf33f039201d1962f2b51031c2a4dd9aedc08f7c895682d1352e9a21225d81c98ac7fd4b4de6efe3dbe437d255e4464a1258d4497e2a1d4ef6c319869b78fdbcf4632743825112fc21acc0a1431d8cf8eb8865e695c0f3668ff5acd8e850373331ed7ae3bbe515b42c1d0ca0b9caa4df0048425fcd08850f23a86b4adc859291b5c49ed54e41778c7ee2a11da9598396aa889dda9513afb9fa0b66c0affa555bf76849d754702163004fe3e77ae5a7c46f3696bbd52cb8680583aa5cac22608c6d45b96770dbbfca14312fba61b3fd0d7041ded80d8dfbdc3f901b10 +TAG: f42a0e4e6e6a1e0654aca2ab7877350d + +KEY: 2c351f0b77cf0920873fb57c910cea15 +NONCE: 4f844d27dd26df3015608119 +IN: 227ae9330bfd5a662af4137ca7fa164f383a63e5bc33eba94726a0e7a27f666887fe484680899ad8aaf6fc5426600760f5e6ba53b0484615d0089d9b1e75f5952ce0665d16a045b272c3c50194ab7b3831b313dbd800168a24e576cab5dca4319660fc6add76bb400376fa29cbcaa25adf3cac81f3e66a6baeb0d94ed92aa37271d2cbd8219c0647f0af6a4ba8a8e169c10cf6354122054a547ba046e67cf1fb424271d3d3eee5b51e94019d450de6c1f770395316421b61c5ee9ff00c910103e58d423946c68369730a974a392c21be3fc8223cd816e7432200390fd7cc3f5160795422c9daffed23df42a7f8259e295d43fe57f75f674886c6405bc6954d17c2a36348761ba09694964646cb86c0d8c64c00 +AD: 9d7d5e5f63267154bab863a7b53e0ba159a6d8a57a8c49e084b513b463a1e812e94611116dce9c1ceab2b7e18b4d69f7dfd225d2bdf5b7750d0d9dc131f22987bc812da5b0a8ecbe9d0ca2210cf6ed8a791d95c3f72898497226f69c8971c2da342500b75367842d14983384b5985041eda7f1cd73e2b5c71bbbec6537390313583bbd53d2d563848fc93d81579d8db321d1bec973f7c4e8f34b6cab8bd7b5789a7b40f599f2f8c43f6d7f8fdf940577ca8b5159e699d449ffb00acee0940937d491a71a81ee9da0949f8fa1d780f3957908819221941f0c5d011bfb2560acf2d7386f973358d68487954e26ea9ad3068c65b797307831e03aef7d1f1bba9ddbba2f251329e85172ed8efb1a689f8026b5068c +CT: 4ef2a097a8e507143b6354ecd94d072c0068c68698fd04f2211a771bec45d616d8eb7eaf90140850c135cf468dab9e9f3dbf059b56efcf616b32992df407bdb735a8b5ac2c361973abf47029bcde46dd5b13728add772264f2faf60f3de10494b0606618c383c8929377f2390c4a104141a11711ba7e3a3c83396761d7d62a997e8782822f51ffd0eaa0e6c9e02ae4effc0686af29f2805039c1cabc8b826d1ceb75c4274e95f854a9f5be709ddf1002481272586aa021acc2fcfe3e6cb0b2a47d124bd8b83585b43bc38599a497d0de3979c30c81536ab06a1649a3cf5dc2c2a6e52bcbb05a76e35139c668dc8a3c038ffd1fde8c1b4a31de48341b5fd586c674e35bef3b104e4b84063889907c268226dc73 +TAG: 12aa2a46a9014800b3243d1020290d1b + +KEY: d94582550b2e0d42255f13a8753f8e82 +NONCE: 82f7abb31dfc28491697b347 +IN: 53ba297d691fc3abd93ea8b6f3d629584370ac045934b1b738a73c09a8236bf5f99f357b1cbb120414c68ee64d304b7751c88c563d5d16fa094602c0ad3c803a8f116f3a5071c049a4b88f19ba2d500a171565c719fa64e691bd4a9c4588077b0c2b91733a30a214e474d868ac6b301898dc85346523bdd4f6c9807ef69941a5369b4b7ff7fdfd252729d3829a7bde65427639de0b2b154b4830f57ac13894bbe705f02362f8b75367ec7962c53bd6aebbf15d72b25c08570392592b6a83d4f44d2037da8cbfea2456696cc39a3272e46a5b4fb837bc6e4bcd9606afa58d3b260e9f6f58bb5d0f07438f378b6a36c1931e9eaf923c2a3679a789e7ef5865c7e799ff4633f1b2acfb79a5a0fe9cdda9cf347b9664568def93 +AD: 2bfb6a6726c6564b31cca749bec29a8c9fd7bfa22f26af0a80db5e6b13a3b10367be6ad87325abc59252453422535466347059b7d57fd2b1eda1d6d37dcfa9da7df34746e1bbc98baeb4bae17281a537fff85c0785f9f27617e77333f11be28f9aa3704651e4ddd72502c79cb2a810c4686147cedf056b5f035566eb34d117c83ae7815e7e1e83163907020cf0736ff1862371e87269e5c8c1926e0bafbc10610a6ba6cfc273c9d9bec0922726dea04acf72b3f88a5fffc57e0af6dddd0396b4937d2e7d52feaf60d29dddc5b4cc139eb855acbb794b99d74b8a93e3731f9092b92b9bd50c846eecb6eaed2e51290cd1f98dccf3fe746c5293e0b970dde72835c44b3a445dc1f2bd67fff6b1a7e378611eaa42889fb92de1 +CT: 1afa2fec98728ce39fba26bcc769e9766993c8276f88613db574773c84c91fce6ee7dc6ba4281b8d2dfe13820723526f0d6f20cc21f305b792e9a2bb1622c742fbc05ca1f0121cb9f6e1ad6c3ba80891e2043adaac4f1bdf29260a44a182cb165f58f480be5f16b51fddfd0d264bc4a18bec589d24817f586fc8bad15df7cb4d48d788fe7fbe69f821b5558b0a664ee12ba8ddc6bbd325f9b83a024245b4e68b310f2282f4cc6005209f7b7aa6ccc025d435441e3bb990e81bcd4c8218b8360163ab266be4a1f5603059db2bb67e541e1edbe8e7762ac522a81f495f5ff8bf99948050e61c86e83134f4e1212f879c86f7fccff472fd9753e27a0601f914655a5f803061cc986431445021c907b3ae0f060fac13f3723867 +TAG: 5ef1ed1e2bf562893b094d58516c11a9 + +KEY: 31d93fd51c2d6450cf35d9edd71413f4 +NONCE: 28f6f0c288c9f92e80252e1e +IN: e78eba6c58f93cc2374932fc21e54f695f2daeda3bd1e0121a77d178e3bf5c0e824a99042e8f2522df829d014e4d35a756780e8c07f53ca8fb78db6fb76754ad461665051c4572b2514804d0a9cbae1a1a013b796565eee13a7832ab8834b8406b1185332552d38754dde2344ff4f6e4823390964ba2dc43de136f2235b1d919e0f4ad60813d30f0ac1dad35abe3bee9479337c7b430841d2c722f12aeaf931cedd8a82053f697fff8d07f0af6013da7da58a5dfcf45561943e7ccdfd8d11fbe96a68a5a27982e47346500c0284caf8e6b63c6621e80503a7365d6693dc9a249093dc45221cfd88562e25910034c2c123e44e3b09d8a8a15547285d2596b98c7a0ee9d10b2cdb032d08a6caee1212420b6854181a583c15e046aa202dd +AD: a4fdd42aad5475ffc1b122170024486406033c8640233cd9b23c286fdd40c5b69eee39cfbf965f7a10c73663f9804e6821c4f62980f8362a580bab446325b009a004b60b1dbd12566b55b42e58d8037d86c1050cd6ecaaac2fb0ef616a15bc5bcd8252fd459165795c500bbb2fb1476e5cfef9549db733be65bde391c810d099e3745a2cc7a94debe1f4ff6653b338123ef7d2f9a602bc9a4bbe757a63f932a802014f2f06c6688faf14332a355b1025f33687124399f55b6a5adb4864727ec6c5334c41d78d1463400925f6c29c0f611f35c9640045a740dad5b4f0dcb632e7f9a3478b526aa9f97cd9f8d3ad094b7922890e7b6d9c67fcc4f747d04ddcd115fba0a8f0433c6fb1bf6011a9cd153f866c76b26d427a25aebc60d10540 +CT: 8d668fb50efda82552aeb5d075ff3977c37929d73f6639289e7c6da8c89c664df80b2387e788d12398d62d3c0ed2f9f918010d41021c464d54f016c4e10e85e29ba3a45793df2ebd6cdf30045363434387bb0d20439f4986e6eb7ae9fd85fe776f7b8035025624c2413ca8491cc6e79fe901b9c40ff3a0e37a7c7e88b56de4fee65861865162821e046846d253982e4ecd17bd26214b0923a4297d4ed9423395d856940829ca5ee74488c3b4d8aa3c5ceade17d8a3f2e45d3ba91360ac1c76d6a29f8243bf49c1d75aa41ba239fa6f3b123e198ba799e3b70c674607c5371894800954eda0264b3b82606433f71371dabc5f1fb3d703232533662920a241f613c38d16b0bad24f4aa3b336af89cdcd2f371e1bed7aaa47c56d17100a01 +TAG: 594ee5c93636cfb5fde940e3d561440a + +KEY: b06d694a83b14768ae26a8f00fb78ecf +NONCE: af11369ee342454cddb8db62 +IN: c01130afd7d3f4276dcfc1ffaf4bb636a85d18e0778df6c6791b6edb92a617894b84cffef6556c834a4800b336dc295e80b699b28cf478a01c54052ab0d0d4208e1865edd6906e3a263862c05f033668d7eb5b42baf36c702d102a6a5c723974e63bec848c89d16584f0d1ec429c87686b1ccffd7626e0a83f9c471cb615541ccb02cb58d10e63ffef171f1affca492ace4d39fbf33bb5126c575963e6b6ef9fd2ee4d6efcae5afe422bbfd9c3dc22b6b47cab8dc04127ff93b016e0f92f5d8518d5bd3bc6edd45e0397440f1a4a0c7c9c2773c0a0cd3b890effb010dbcc00237dbed1177b86bf60913309bfda9376b4192da59a360afc5bcfaf8be16ea8313de97b417aaddceadc63a1c3a355693616413ed4101ad68f6e6aaa99c839dd2a9ff536 +AD: 18e3195358bae4ccf43ff8daa34902fe48f99fc1371d34060aaa442a43016a1d756f795fa5c9c4a828525554571e18c27134f46094790dd1e68471ee40c17bfa02f175b2c2f7f2aef20f00e4d71926560b58f015de19c871d808acdd341675d8fc19d1e6d4028e1e8926df500c4685c14729c6a056898cf919bf3ae429fa3ca8746495716d78c9a8f2ecde596f985b1c25ad0e73aa305a86259319176b4c4f3bb231fdaa478a856f46416ddb10a14ed23c96dcb86f5bea3114568a44d8fc6ff4bb47fd0e2538b70d964842910a682e7bc7c7263249832c21b7083a1e8b143828de0f3dea8b404cbd82efb19a11e4d60aeef13abd86621ccbc3d8f220715730eabbe04a6bf0e11a4f78cd2c4369ce2447a76f4fa48ef8d322a8a28a67039c24c4bfbf +CT: 6beeb306c71318cedabe3877ec916ce2074b2c3f1df887cc3a3e8019c10d353854b6b65c947359138d5decc62a42d50921dc8f6cf63a16062af47aa8cd50d0b2dcbc3300ba0d7d069a5e4b4fe03bbf7062c6001e276be116fdd00d15a6399d1b0db71c58f396f8bc7e51c2b1f47430d4ebd6c5d05328b29aa79bcb26927ea5a40c82715aa0e36cc83ca6d250812c1305c02ed4291a25762cd709cb3d808031b5f918ce253f622c1afcb83c43707edc493d18ec6f0dba4353a1cde7184db65654088fa13baf45f7643f0dfedf4058e6095156b791ed30827c556a7721658314356e7a3f3c62cd62fe938b008cda56ceca71442fa0ffeb78b13c5847a3ee9668bcd2a01c753bd797c240378505d1e8f2b8905428b23bf589de9af390f94f21630d1826 +TAG: df5a21a399354b2b3346a9eb6820b81f + +KEY: 06a4c6a8aa189134f5784a525d46ff10 +NONCE: 0f765d3893af99f5c3e6d9e1 +IN: 706b754094869313523493089e591d34868b708cbde9bd8b42cba8175d1fdb6a8769bb9ec156d44bcb8f9cbf2685a0dc18b5a802dcf7a12570bb9042a0aa53dfb19af8c0f13763f388d9626a480d6d435dd90fbdbb4292d9015a5633252aa0583498d6f7ec54460d8589c1d6a6d16a349d10ec6070e1cc52e5fb996f810d333675a7130e4f3db9f4db0e3fd3541d32e0b2efbd40ba70cd59295bc8d08481f0f137832b01bac1778ffd7450376e174067b3ec23d0495cbf936bdc176cabc3f42e2991947a4fa87dd8343c32fa3d7ac0e2d22660a0c128a00e1b51a8742fdb2aff44540e39e588c5920ea16293aaa522513c944d3b77f3a0e90bd9105319c170886202e336893d100b0a25aa609a49a8255f78233561f7b88256386d1c3c002c3ee68f2775585c65 +AD: 18e2ed6d500b176e49f7e1b5074c0b7dbfdefdf00a63d9fa2fea8c5e78a1c4ae00f17b23442933543ac864097629e112a099f3dce6d5beb1e3f3c8e19522c6b8f615cbe23444bc91a802edf8a08995a55125da805ebb073fd89863996ef708f7293069a744ad95db8c17cbcfedc331119e85020df8852d74b8092fd38ad424f3da41b4775beac19536ed801ac1069925b12303d8ad2c52c36ca5b4ec95e96f02ebc5725ee6cdc099e666d9055b789e39ded77a8fdca0fe2d94b8039be55b6a75209cbee4fc7864957402b50427db71bc75a0b1e3d2ed6ea20f12a980c5ee916067d0dde7d686570d075da4df7088fe5dccf0d440064a96998da6f318b603d513104c723f27484780bdad586ee358d821b480f9569e4dbdd1a45ab9056f8d8e5a879789a0d65338 +CT: 5f3627bd53f8da0bbe6f3c9246d6f96fe9abb91cdecf66ddd42f833d98f4d4634c2e1e1ad4088c84c22191bdb9d99ef227320e455dd112c4a9e9cca95724fcc9ae024ed12bf60a802d0b87b99d9bf22590786567c2962171d2b05bec9754c627608e9eba7bccc70540aa4da72e1e04b26d8f968b10230f707501c0091a8ac118f86e87aae1ac00257aee29c3345bd3839154977acd378fc1b2197f5c1fd8e12262f9c2974fb92dc481eeb51aadd44a8851f61b93a84ba57f2870df0423d289bfdcfe634f9ecb7d7c6110a95b49418a2dd6663377690275c205b3efa79a0a77c92567fb429d8ee437312a39df7516dc238f7b9414938223d7ec24d256d3fb3a5954a7c75dbd79486d49ba6bb38a7ccce0f58700260b71319adf98ab8684e34913abe2d9d97193e2 +TAG: e690e89af39ff367f5d40a1b7c7ccd4f + +KEY: 31323334353637383930313233343536 +NONCE: 31323334353637383930313233343536 +IN: 48656c6c6f2c20576f726c64 +AD: +CT: cec189d0e8419b90fb16d555 +TAG: 32893832a8d609224d77c2e56a922282 + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: "" +TAG: 58e2fccefa7e3061367f1d57a4e7455a + +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 00000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78 +AD: "" +TAG: ab6e47d42cec13bdf53a67b21257bddf + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +CT: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 +AD: "" +TAG: 4d5c2af327cd64a62cf35abd2ba6fab4 + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 5bc94fbc3221a5db94fae95ae7121a47 + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbad +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 3612d2e79e3b0785561be14aaca2fccb + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 619cc5aefffe0bfa462af43c1699d050 + +# local add-ons, primarily streaming ghash tests + +# 128 bytes AD +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +TAG: 5fea793a2d6f974d37e68e0cb8ff9492 + +# 48 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0 +AD: "" +TAG: 9dd0a376b08e40eb00c35f29f9ea61a4 + +# 80 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291 +AD: "" +TAG: 98885a3a22bd4742fe7b72172193b163 + +# 128 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40 +AD: "" +TAG: cac45f60e31efd3b5a43b98a22ce1aa1 + +# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +KEY: 00000000000000000000000000000000 +NONCE: ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606 +AD: "" +TAG: 566f8ef683078bfdeeffa869d751a017 + +# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +KEY: 00000000000000000000000000000000 +NONCE: ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c +AD: "" +TAG: 8b307f6b33286d0ab026a9ed3fe1e85f + +# 80 bytes plaintext, submitted by Intel +KEY: 843ffcf5d2b72694d19ed01d01249412 +NONCE: dbcca32ebf9b804617c3aa9e +IN: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f +AD: 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f +CT: 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5 +TAG: 3b629ccfbc1119b7319e1dce2cd6fd6d diff --git a/external/boringssl/crypto/cipher/test/aes_128_key_wrap_tests.txt b/external/boringssl/crypto/cipher/test/aes_128_key_wrap_tests.txt new file mode 100644 index 0000000000..561ec90b25 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..4fd75e2bc6 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +a6441689e7569d2a8b8d02bad02ee7e4281a7d3d \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..5f2fe28ff5 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +06ce309b334fb4ddaefb19c1c33fdefbece01a52 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..ae8bb4ec98 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +9cbeb39eedee59a9a40744c2b599daeabf0e2d59 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..880b265be7 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +c61427662ba032d0a1797b841affa88ce57bb249 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..a0d2482313 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +9f38bb012cdf08a50f1ba070f0b8815217752184 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt b/external/boringssl/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt new file mode 100644 index 0000000000..2a72e1c9d4 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt @@ -0,0 +1,336 @@ +KEY: a5060fecb0a738d8ff6dd50009a757c6e58db73228534d03f32c26baa1c209f402c3e03a6947c1d9421d63ce43f6df26d30ce783f5ed0d6b88edd389d9f92d8d +NONCE: b52227e92203630a79ec7f5c +IN: +AD: +CT: +TAG: e61a28f5df7061b4236834d2034d2b62cb63c660b7de696c26b345e66b34d222 + +KEY: d676047046bd5be9263ae39caaa0f688abb1bc67c083658894da6aeeff80b6d58ffc7ca1a1c88f49e629bf5544b2cc7669367202b158fce83fc4a4826dd90a7c +NONCE: eabef87a00fd99ebb6ed6d25 +IN: +AD: 83 +CT: +TAG: 473cf728899cd5fdd54f18d6f934c3901f7ca118fc5ab2cbb837feefa7852a67 + +KEY: 5eaef3b8e068fbb652bd37df4dfad6490095642cd49761a35476dffc2b5b5f75236d0351d96a9028660788893323a777ea8a2ac88bb5e500b334af02b1c2a648 +NONCE: 34d049342b9db5ffa039eac0 +IN: +AD: 7578949699d44dec9188a7f7e14b0a23637cddb9107dbb1f8e2a968aad0443356d7eeceff4316ba7b2e8fe +CT: +TAG: 4d2612c21357638bada9290d2a272f10fb5f070337bf87bae396a1e7253633ae + +KEY: eb7b3d7eeb5f26010915a36837dc83da2bad07eba714566584bf1ce62fa9b61210b0ead7182bc28c8f0427699bf04786583fa32f3c3a8a6582cdc254930043bc +NONCE: 3bee5ebcdfc72f4ab0023211 +IN: +AD: efecb57e79a326c6b2ce0ae74d7656992a005fbb8da5a55b9595fc5348a5489ee2e69541ec0e8a727a560625 +CT: +TAG: f457db1e274adabe5fc898fb1eb7c4a5a8e9a2b66f964d0958aa058c1f9e15ba + +KEY: 1c1abffa8a2667a8c1ab347860528162d316d58e3966050dc140fd360e6ff7c557520a8982aae97c5db5495d8951eaa485e1cac4cd8f448a13d071d759885474 +NONCE: 4fdce4e59bfdf5d9b57c78e9 +IN: +AD: 55125cefc919379b3b4b2a24ee1794f44ac66fd99b8b68f98d4abd45ba50a5b76e5375d08abe3b8b8d3c576bc8 +CT: +TAG: c021d2c73737e54ac6e7f61f9bb44818e5bdbf8d81d43842fd25a535790fafba + +KEY: 366cf53bc185473acf62610b74231e53aace84e9c5d6fbf71fc24db4f42956065d3eec01ecc72a6c89266565ff530075f4532c860e3192e866b41aee98c5c42a +NONCE: 9ff54bd7b10f4fdfd8db76c7 +IN: +AD: 853ef59ae873bf0bfe1465e9dd8c2cddfcf123d213ba4f599d984e4ea69d3c85a23508ec7941ca740a9157ca2a788e9b519291240b307d6c5a8c6860a96b4be698659d19e31ab0ac7ae6ba31dcd609c1db67ad580fe4422e42d368c3e93a56f2a087b0d587188462310c2ebe58ecfcf7178412223808eeb2eda76446168730fe +CT: +TAG: 12d869dc4bd4ac4ce9ed643cccda9e11a1ade65c76f7c1535fa4ec2bcc5eb4c3 + +KEY: 147b41369bed390f0a9561586fd975474e3b3bbf7f7ebb7a35e5cc43b516c044dce93e154ac790a109709ac5299bb17b709a913d33fd57ebfef2b48ed66393b3 +NONCE: 85b81732d2863b41d2551763 +IN: 73 +AD: +CT: bc +TAG: 47fd81f6eed8d3c66afe06d788ffe40717847785f4b4c617d75a11171690a60c + +KEY: 9bf35c1194659c1da634eab6707c55b853c8f61d087187162e926adbae02f8bd4d15bae5b05865d0e2236d64715fc39f32e4e3679a0309396c37eab13d1c637b +NONCE: 8da14a98ee741a5fce0de732 +IN: 10 +AD: 8e +CT: 17 +TAG: b76af41002a946af4947f98f42a873b7da0871f482990a70bda8f005274ca179 + +KEY: 0befac10caec674c9f23676d121f065dbcc8c91852dd5eb4e80c41076995a2138077592fec665954d21fd6787234d32d3d54bf9c220cf2bf018b374bde29926e +NONCE: a96bfb49f3a136840a0e32ff +IN: 59 +AD: 236adab55e1bb8a8db384c01bb2afd30ff35da71f955fb217b8305a45ee075e7f8d863d4c0e5dbe36e297c +CT: ac +TAG: 7bb634357e0835b02a0642352a834ff6598c2ded1af8e8ab60b9ef0641fe863d + +KEY: acc672aecf6f10119ee77070abbc2b4fade7e910efd1f93a5716161f88606469a49df05b40332b390d3ac289abfdf6bf7c37c033b1671082922d939139de0d42 +NONCE: af0f57b55f1a73794b3ce5cc +IN: ee +AD: f385a50ef027e532635878a4df0deb23369774be47c42f17cbd44925b668f628338ea5f8256c5ad8219c13cf +CT: 71 +TAG: 13a5296075ef23216c2f2e83b940d24e8e1e6a01967af96599360f11499ac0a6 + +KEY: 6195ef5ce3ee01188c48b04ce7a28b3ddd04b78711a6d1233121fc8ec3db3a7a0e496d1b6a416675b1e666b9a3df167efb8ade29e4f22fc77111f32ba8bd1ec2 +NONCE: 092070b2f8b65fcfe646f6bc +IN: 26 +AD: 98526dba4437d88f657c0b7ce2a2be44ef4951711a40747a7d14b195e4c0eae97247256bba7dbd93d6a8f738c1 +CT: 83 +TAG: b6aad3f91a26a38245031d6a7eb97be0d386939d4536b2a27c90a2ddb891de73 + +KEY: 40335487f9958dfc00b76ff06dfec162ae5c6be4e26918bd12e3f21760cb0bd364521a11f5bfae11dee989627525ab5295ee404bce476c280d13d238dea1bd40 +NONCE: ecf77c7c827a34efd8cdf79d +IN: 34 +AD: f6e661254bf235c7d5b8ee330cb754087480dec5fe4c31dee65d1ab4479642101404bb563522937fb2e41d3aa8a4d269a222e6e0bcfd07ec4b29c1185f99fff7cb5bd2ca8c5b38742270e586c8db19138b446833f2ee07a11dae5b6a1a4c28657f3380e84bffe1bafeccad57d9cfea3da7f728119ec5bb18b79e002954f4379c +CT: 5c +TAG: f3420d4cecae2c1ad79d977abbe408045bd87525c0da2b93e0af3e6c53ba7d74 + +KEY: bf32ef44c7ca9851f397e70df736d7e0e6243cfd875ebb81d76ad7612dbcfd084cab6b0d67c6a6e8b567c93fd0c3abb78ae121fdb3051a62ccfa045692d3453c +NONCE: 46e0cc64d6e431c1efc2bd2d +IN: 959348a8ad6912d7d6c8eae52f19b1 +AD: +CT: 55e8cb6fd958f18b3c19451c5c79a7 +TAG: af09194071cb0ed4488d27e79700f938ce77386e5d772f9853b17b719f2b1ebc + +KEY: a6b5b8b051edf5cea0353ead88ea887fab048ef32f8303275e93d8f926da0d4b0e34b9447cf44fa70c24c9ab964380065398336bbb20be167fc6cd5e591ef50e +NONCE: 371363612c4675a2e59ebd39 +IN: 443d16621b0cf9a12552216f9558ca +AD: 32 +CT: b7f432eeda8e4b8a25f0445f17ca7c +TAG: 649934922826febab4d59dfb52a7558e6d30d56e273602b98f3c55fd8e24f4da + +KEY: 075b75434269a3fcc57922ee8cc55b5bbe1b90516a3b71838ade73d41ed1d1f33ae1e0e86f88f6ed7e091cae3ccb05144b3ef239831554d6e79ff97c4d8f150e +NONCE: 754d5c4ccbfb291133859de3 +IN: 62a151add825077c59459fbf82b708 +AD: c8db27487de71124a95eb6359270a8363908159200333b46ee74e2709b308878779686bd43c24e9ecabfc3 +CT: 2ffb9a9f65c9fe3daad13768ab56bf +TAG: 4430a90fed7d4b5b2adf5a60d6854956be4feef497781ac7d864a04259e99516 + +KEY: e787fdeca1095f2f2760a1c5e0f302e07d6b08de39ce31fe6a0db2f76e4626eb0968768ae04d37082c114573c307699707630b8c7ceef60abe3b7831d2adcd6e +NONCE: 9dc9bcfe8b4e2ea059e349bb +IN: 3ad57105144e544f95b82d485f80bb +AD: 96bce5dcaf4a90f6638a7e30cfd840a1e8dbc60cb70ab9592803f8799f909cafe71a83c2d884e1e289cc61e7 +CT: e504109cdbf57b0e8a87080379e00d +TAG: 1798a64b5261761ecd88f36eaf7f86ed3db62100aed20dc6e337bc93c459487e + +KEY: b43ab650bdd201cf05e0436afe89ac54867383f04c5ed2faea5db8e6784c720d905234f1f5443c550ca14edd8d697fa2d9e288aa58c9a337b30e6d41cfa56545 +NONCE: 4e3dd3efe527902b9de45a5f +IN: e386663e249b241fb8249cfec33ac2 +AD: 3cf7a396e1bd034ea77a54ffca789f206f94263d90d98bf3e69cb42205fc5c95cfbd0481b0ec490ea447299159 +CT: 94aacf00092723e778d25ba78e9d27 +TAG: bd5fcf90b9532e7abfa858aed90d5170f08edcdd28ff2c673e0ab45b8c0a0f39 + +KEY: b22a7c5bb38715025cd59cc0feed9ad8e51101200000168052b294fb1ead545a517dee636a7acd22b8283afb33d30adbe02c1c8557715eea7147f3d98a97cbb9 +NONCE: 3b4244c9ad9fedd3f10fdf7a +IN: da79e1ed131856cec3250fde7bda4b +AD: 4b77472ade3f06500169405b86a793d63cfa58f57bde0dd706f369b391142c2fa8a3e6345ccf0a9c29b2182f578e22f55c576f155a05be5e81997fbe06410034ecddd871e5ed94b5eeffc6dbd90a8e66449da01f8ef47d28a4a4bd253ffc427f868867c73b5c709b01732bd8035b1a23ff0a903def1eb136fc90d8b3c8279769 +CT: 5d8ad7abc047bfdf9d9cd0b0aaa53e +TAG: 41d050d518d0e51ce16bc2920aa6c76eb8eabd4ed76373c59618c6354885f47a + +KEY: 04b3fd8126d65f851f47b3dea22cd6e32506f21effaa3e29820ac7825e01b51c5a2816f0298154f2d8addefa2fdc34c0635d4d6b80ad23eb320c4d4f2aa1de1c +NONCE: fae1b1da40471dbdcec64d4e +IN: 509f116ef7435b0640cf141d5b958aaf +AD: +CT: ecf553eba80e6dd1fae2eab24d772a89 +TAG: 11473566e80cff5d7421f65949c34301f34de378e91ad50928cf2caeadc466d4 + +KEY: 413d154dadc7d8869e9e0f24b3320019a04b7a37620dd9e7aa40b5c08d70dea03c12ccf7faad7009e972680e81544b647650c6ff033f56e5bcdac9a35bd7f804 +NONCE: 6a4404adae3f4a7bd2bef95c +IN: 3539fe02b75981fad4f8762772b3c11f +AD: eb +CT: 3f8a96905609a4ef1a95fdb87337503d +TAG: 8ee076fd624d90e1f6336a92165e80408ca6f0e165b201547d351177c95e8d51 + +KEY: ddc10df673e720c00f28fdfb69f1b8fba99696f23b6f29704a0114444cc0c8a6c8606e8d37fa95aabfd65b29c655678fcec50966c8758a3fb15332a1854a8eac +NONCE: 06331613842b4af86c13f8a2 +IN: 55d74bcfc3d1cfc716c6e6b7153c6369 +AD: acc264344ae79959f9dd5130664273ba6f345c3fc7bc33c6c1ce33312bfbd5f181a3c7a24f15e7acf72ccf +CT: 20650d9e846eb42854692d438b21d5e8 +TAG: 973857523e7ff600cf9bcfcc98403b34ab38d939a6d76716beac42678ca5f5bd + +KEY: be0c884db54cf761fc24ff3dd572362910dedacece5e1d93a916df277f923f78e7dcd908e60beb0043503c5b4877a9d962a7de37cacc7387a7553949b52894ec +NONCE: 3f027a93e2716668c7634195 +IN: 1ba8f3a87ac6738167aac1491b602ddd +AD: d06dd1b9360a68afa3de5d239b6d91d212c5c555567545a4f133bf5a3b0f26addb9379e1cc1cd690cd427c57 +CT: 3596cc50ae72db932dd83bbc8661641d +TAG: 44a1834b1587d0f88e34137dcebbca059dfb8f65ddab18f338a8a30152167be0 + +KEY: 2ee848726730c64332877a4f88ad7fb241a73b71fbee8eeb4d9d6485855ea32b487e03968e1a7b9e8ac8ab7fbd84257efbce0aa207aeefa67302d5847e0d9c05 +NONCE: 526b0a79b6359d133ad51011 +IN: a0c0477e8a9ebfd275b674ed33230d42 +AD: ded2f0f3f28aea28b17aa58d4b906c6a9b3078f97ffe95b7e161b0c3dbf66879bea7603a046da4945c802ac8b3 +CT: b1691c8275f12f7d9af85e71dde9dd5d +TAG: 65a5742dcbc49295c4805387e0a15f986ae47e51add9389dfabb6468a6e83013 + +KEY: f4a7c0e29ff510c034778e47bb30a468a92140a707936d381b1554d421af107c578e74c53ea08c7f7d93cf67612061359ae458408a9c79250f776ca4192016c0 +NONCE: 025bc10dc99346c4d0766a7d +IN: d449a2e812429beb5c466d344f5b5eec +AD: 304dbf9a59bfd33b777d8dec9dddce4c365e72aed851210eb964c1da18119bd13248266a67408e88ac2eadfc54def0fb57f23743d376b11293377565d253d2bffe0309f2946cb78d4e9536dde4691fe1eef9ce2dc916a773d06b42fe2b014e7974d4aeffce25a0902c9b44265e5d6d26809b5f24875e80cc13f1f8872b04a237 +CT: f366e7b66683f52586e1c363c15b7fb1 +TAG: e0e1bb733471f150ddce1b83f3fc2d88589d286ca052574b7f0735bb598362d2 + +KEY: eb78ea626b219e12937057155884547cb7578718f569dc8f2b370c0fea80e7f0d0f5cb590f0b7341d20c775bcd6a3c818e23b6cea949cf99eb94a23a81cd2249 +NONCE: 75a10f16d429b809cf12b9ef +IN: 6b0203316e8108ff01b12df91ba6644382 +AD: +CT: 7ee07054f76471115be159259340c24391 +TAG: ab970669d1603767d588a93cf215673ad307244f9179f46fca56e97f64a5fbac + +KEY: 3221167926be262b7bd0591f56be6bf030365d45ab84a93a94ea41a5e07735b17245ad43787e8791e7ceaa0472b562ed17e3b609c66c868c9b08304c8bb328b1 +NONCE: a94d8417d2bb0323bcfd354d +IN: cec81bac7b85c441b6261163d67921eb49 +AD: dd +CT: ddd8860fa9e2e8087db30c9da1ec9f9487 +TAG: 26a3b9bc4d4cd802cc22e7647a19fc2a5092293c9f5b1c84bdab7245a6d8f4ab + +KEY: 4b16e2d62294f76cd2a6c8e0928279d9de40f0b169ef9465738cbfa064c520128ee89cf657da27e4e532d8c4709d992970bfc9daab2f31b3a67e53200d3d6710 +NONCE: e746d498b9031007332447f7 +IN: 16841e3fc1f53990d33f7ba525dab121a0 +AD: a785917bc9f3aaadfd170abe83bb30c0c5d595fc8b491d983131aeab1a7b8d8771f1a963c251976152dd63 +CT: 6bcf5eac15ef74cb8a706856f62eb5e8c7 +TAG: 9dc84b06e8ec8921be4bc7762e8cebb61a95ac5660022520f9438e8f77b45796 + +KEY: ff2f5944111226df1d9a300533d3e871694fe15a418b2090265cd8c0111b249dfb7ee86bd9228f7ea5d89d8afcf10bf69942ee4c29bfa8409b63c00c2213629e +NONCE: 477060f0c61555873bbeb225 +IN: f091891c43e2374c2755a88a11b04beb4a +AD: f1323fd1ac4de9719dc5966dae45dd7b8ddbee3f8da4f4f4d5f25d06bdb8ebf57328dde76d0bdb9bdc5f6b12 +CT: e0d96f6f3ed0493a289d4c3b79238b9ed6 +TAG: 71276c05b52bab0063108dbf4e8ff57cf3e15079055a309d725f14bb86671ce1 + +KEY: 1ce841bcf2ad8accc458a2d94774c3aa53a99e7dbec587376212101303ca2b42272a23fe28514be190b82e503e7772a3713800f4360fdb767e85ea5e1f7b8eca +NONCE: a2f8afc5ceb5382882907630 +IN: 620fece1e843d1d0b5c5a541a6f615a81d +AD: ded910647464d0fbb0a5d93ffb9839de3360c675179c5991ad3470285d79071436025111153628c563ad1b595e +CT: 34431c3422e009373c50f3ee6c5b3fcc2d +TAG: 6e4e8a3967307f47e233a36ce05a4826a698fada2ac19543bab7c9ac4f79451b + +KEY: 6bafd28a32690851fda667eb2d3c5993f13df52b2e97630527f26c498fd5019f26177a78f27c0c41616d2a4a73757fcaf9cd92a7da8498f90315d41e7479d90a +NONCE: 75166c506c8e1d10da4da8b9 +IN: 697bea4d6eed5e6ed243cf01cc79bfd3a5 +AD: c0fa663961c3f7e09a8c7bc73e252a232977dd6c9483f02067b34fe695f341d05338ea2002952439ce08295ee5c12f38dafffeb5716908d3f1d4bfbf9eb0e4077bf8e534f19568ed04fca3bbff95da9088cb939f7a20cc97cc0994f9308e184219bf12c8af0d66df436c296ad39832d661b88c98cbb168c751719ac1383c9124 +CT: 8f37885b9602725385fd9a244ab2a156ea +TAG: 7fa5cedd330887900f4a44d098e04d5eca16cf94e21f897fa54b0fc116b711b6 + +KEY: 815786c7744d15afe1d6ab452cb6696fead8b88269ba3eb35c458f6248bad77b404acc744ebb74612c4f97deaccb99a7bcc6ad41917d61057c05b30c581dc4a0 +NONCE: 12342e4704f02336ebfc91df +IN: 7f15e696b49ae5104ced5bebbf58a9d8ddcfaf46ddce9df88fe0d58a2f8546feeb83b975c66e4dafddb7fd9d17e80127e70af06b3b8b13c3390f1f50a227e7 +AD: +CT: 22e7c5d54a7b622c47a9edb77cfe7c094e500b0ef9595bc346de736e0088e5934dc07160aea34f24d3ab21440878213d28059551cbfdaa418af40d344674f7 +TAG: 8c271ea5c15aa771c900388267efb2f435f001c2e83f4ec297e77c608de2d579 + +KEY: 66d87d2b18e46257476456a1f87123424477decf196b88b09acfd3ca74bdebef4c98f1b93803098a141e0acc3ce8eede065417a0c1eda9b4614558d2383762b6 +NONCE: 1ec0ca1d3b09ef186ac4bb1a +IN: cbb59e14098c2a8ab7e84ace913515c74e056e0fb272c7b88d0dddfb62e395afb695647d97d1071eb09cc1e1776b609fceaf4e30e92640379bb8f0e762ca9c +AD: ec +CT: 832804b8003b0ca1b4eff1dc4da6f6a9649e5a582854bb72cd74357476bf38d81ea3bc8ac0463f21fe37683bcbe07360d0ec2d7ab90b588adf669099303ac1 +TAG: 9fecafc768fca71ffe7d640dbb7a052d97d6c8e2fc86001d71feaf284ab609f0 + +KEY: fbff97085351f4500e73190ac139dd3ac91e268042b5926b57e0394c750b10348b47641d195d5fb5b0846256ab229f102538b81e209db5d93b4d55f30c453d9c +NONCE: d4868c918de2af7d3e3f57d3 +IN: 4f14aa5a680d66ae15ce0ce4739888f64d827def862572f9a6cd620badbe4ee9d75f4f9bc1f73d409f519a657f53a50d50e68e22f33a8ef5aa08b1212889e5 +AD: c41253e96696a948ce500030af27086842aacb79c04cc02a42b858a65c630065a5292bb9b2e69ea5fe5a7a +CT: 08596ac0550574e352edc13d7e390d8fd0a57406dd61e1543066b4aa0ea06670f356e26ada0d6c61c1e41de1b4fd7a251c961fae44b23523ce227eec99a338 +TAG: 72f58de3e6697c8419ef518748fe0bb3cb930907c71b6d682c5e61068206d991 + +KEY: c78c550aba82b571d39ce21d6ecf5e5f7c2a7bf921c6162c64ec1fdff4d0b8c41bfcea0e2486cc86b9ed9e9ceb73c4ec228a2ecbcfa0379174e76475cc21ae31 +NONCE: b5adf4de19980a71cb8ae8e6 +IN: 3d5e43ce95ff9d7f797f27b904c07291a35678fe76a9c57f0c0cba724f38acbb22c6c185db864a2a17b7ef2d67a04810ee5a45fd5a4e28a15a1ae16971451d +AD: b5eeb9a18d436ada7bd5601944784f50fb0a989397b5c781a2cdf29337315dc7664f3c1cbf17f37fd0cc8b30 +CT: f91f1f20d06ad4480ff233480228994cfa052f9bf3038d06d997d31eb68bffa4960341b93eb5ed2260341e6816519c47bf231db2a41ad8a9719f4de6a33de5 +TAG: 6e5eabda421961e26dc17a7e1f750425235df4eaf9a97934c1e1b4439fc22791 + +KEY: 17b90dec44546d9dbc489e55a01f2cc64452a9b0e50506a8ad7c81bc6fb21328285cafed901a7204048866ff3bd543003fdcbeb3e9e2f3d580f9062362879633 +NONCE: f0c0cb247d210031f9b233bc +IN: 75b9b524cbfd1287259da116f536aff56112a406f069aa08f545b5372d45b66d7a5d05e02728c4bc2c779609dfe251386f78c5f48b9dad90b363d324826cd6 +AD: 8a604a9b06ad595ce0b9ad1644a596c7d3cde81490abc80840c764c40d6df08fc71d1e8196eae0802f8c8dfc24 +CT: 23ad62a668f942e613c3b5a7828142048f1f6a67f7f0e0cc8bf3fffb2d1dd967da472d080353dc9c23b900a566f20afb850e4a47688ee507faa6178fef2afd +TAG: e9e82d3221f964d9e6c09d761afa3f05d1316d39c82618a82dafa23607bb40a3 + +KEY: d5c09fe24201fcc3ad4c9a9c4b759345f643e930301c3714f62c8dd4974bb15a026b217ac637b4f0e8d6ef40f36be967c50aaea83b2e72df18eeb9576865f1d8 +NONCE: 9cfa0df1fe0910b33ee9849d +IN: bfeb3d86ce3f4c5ccd0c3945e1da0e75dd057aa5b4e1f070593394f4a0227abedac0b77478e04d498506245b162e909cb711d8b875d33f9c4578e80a0e2113 +AD: b874a8523799554436a1174ab124677dc2ae2042a436c85065c50d5b5e7519623379ffed9a9c2b84b9626214b13c1806b65a432ba79066ff28ed94d17628f5ff84618593954389181e997ebd245d31f520539e250b31c86b99992983820f79e74aeaacb3a95e690e2841aba5a384d0333ebaa5d1fde06b4b8e3e1cabc6639459 +CT: afa649ea47db94936f89612ece681bb175664a97aa6faae5745f49ac9fcbfd4287b73cb58e8d8aa12eccf309182f075098f339db697fc60540481dad0cd82e +TAG: 9909335130df0326650823de5a4f5b6f45e6941a6a72ceaf80ef32fe67363944 + +KEY: a13c4654606f532a8df47c367dab1b214166e4f7188c20560831ac30ba5e58d316d29764e4c716ec0126657c926ba2e4541da062447228ae61340a951101b4a0 +NONCE: a2df3417ebb86bbb2f954939 +IN: f1954e59a319547d32e81f846e0c79db41c681166b43eb9c10458948606ced50a44df26fad5654a7c25d3fb52539cf25fcc1c11707c4b5aca7910a76e2374740 +AD: +CT: 374726a4691f178a4c0a6f96108ba30c4ca8a30242c14e84380969473879d4a5de580fab4cf6ef6e465560a15028ba78a1a88f9e62322cb698b15ccce6ba83a8 +TAG: 683e5a3e61d9d9c8b170f1d4eaa4f74dcbecb1a4cb1551dc364bbb336d4e4109 + +KEY: 0c1751677a9b7373e0c2ceab2c8e4dab50af22e2230be3187c21ed46069168d173c28a7474d8f7c3cab39401663405aebdcc474ce136e1fff9cfc520bfe17ca6 +NONCE: 38bc2efcd97998de1528b064 +IN: 8a3c6212240bdcb86da98f0e3ab3e9e78f7f61f0627ea088ab283e739a0bed5c360eeed26cea43ec09b4f3556049a1d7f8ef86abfd1118f9c0e34cc6eea4544a +AD: 20 +CT: a1a9f7f4750be3d89fc4f25917f8ffa7dd462ce712ddf61792a01b1840bc8e428000372252f1b41055416a961db3be8fbe774f0a0a71a82e79e74927522703a0 +TAG: ae24708df0d5893a902765f6c6c2eebae0c11312936cd415bf4a74bb8498a367 + +KEY: 154c21eb43d8d556e5f782ddd64d577ac8066fa172c2936fc2b2e875aa437f941819d9ecfaefa2e388fdeea81a0ece8dcb7647f2c68da48884aeb1315b577c09 +NONCE: e14d1bd8681373d41702a762 +IN: a2c880fcda87d9d4681a735a6790d93a1c9c68e55b87d5f7b3146665a6b2051398eb9895e1f5d522841668b9915633aa8cb40048c619baf6d63ca2da486cdeb8 +AD: b0b725cf634349ce1d3ac49d48313a09697efd9996cc5afd06b1d0817181d0374db05825dc2f08207bfb3b +CT: 1cc0db5980863df7a40c78e323a78be6c6d556d4e3b5f930d8d0f2c6a10c6477e31c000d3f0563b46e1a4aa566a4ef4b433e17e94c43338b51a7a3f862739b6e +TAG: fe005424112de2a5ca6e68ada40984df1ae5ac666cf5fee19e9a0f203dd69f52 + +KEY: c34482341724ee431b5272ee2964b245d7657778f7927cad4b5a1bc30a176b1eb88a83ac9faf58215a72855edf94f8e86fade58c5b5907994bb8381c9f21b753 +NONCE: 4934d9afc32fc7e2d8851594 +IN: aa3d32adc47b0b84d1b038ddcaeb007a7d5c96cc06a943eba5da6d0d367625330556e67da099c84086b3f46bb4b72986e076eb426913e415cd20bee34e434bd0 +AD: 076a7bc587b306f3da3ba88e66a55cb8125bbf8aa000dda266e950f381e35ac938ac86f8a15a83022a25f28b +CT: cf017d87da8927e42c1f10fd3d73cf483bae43f4e110363159a9fbb7cba363930a0364cd42a5de2c70171edc4caf15bfc7238f7087bf1402b32c7bdb1f493393 +TAG: 3961efea656aab1b83082522b801fafdae346f7d4be70db1981283f323e5b5dd + +KEY: 363e10d8b3fe349014d6222761bba7af86545dcd1812fe2e5ada564c5008f8ea1850f374208e87362afa135f20f9e79dd0ad32f86448263416086d3afc5d37c0 +NONCE: cc545928edd3b21c0e8bc0f1 +IN: b68e3a54d17dab6eb41b03de2df14e792201d78a9c1cbf341da421da82b026ff471d4305ede5c6baae162a098c73da5cab93f30d6d540b4eaa0ee772448dade8 +AD: e21498edf4e25ada2dd6a382eceaf737623e501db34f5c5bd5c963f45818b146a6e45aa92db2a2069e55d46a4c +CT: e4920c1fddb5dfed2268781fbb17e9ad2ea88bf2a0f116fbb7b309b25a5b9f989e1abc334999ab175b65f87e874d8ba80792044b458dc27d2b24c989d24385e1 +TAG: f0dcfa064cdf042e0b9a0443d634c38695dd09b99dadc647195fc2ad53dde547 + +KEY: ae93f58aefa94e4e0622f2e962529fd2efdab840fd0bce62e163ca0fb004ec3b22e246073614203d9b63fe2842ef5903ed08b3e52abf7ea18acbe16fa8f66368 +NONCE: c9ac237c87270f2d88b91b64 +IN: a75f49778a6c03b0f8915f5d09efe99c5f4e9cd928713882e6b9b78bab3541812db41792b893c7e2259debc6c660ce708851912a5b9eaf91416d86b5de114ce1 +AD: a4b198a329e9c5bb6d9f31a6415811eb33c79422b0db130b78d788c38c0b9a5122688cbc50fea811afa20789465f9ee4362336cc3701ece701179af96eb7c86d5a00ed8582f24364393287d5dbc3e83a82b7a585cee5b152b5da40aa45ccd46dc841004778998c7efe9eb43c9762d1c8581eee64e18c5a961bda5aafdd5cfec8 +CT: 453fad9395106a703ccbfe811bf775f1827ea960c71d79242d2ea0e3e31b14baa76eb6d107dfc6e484f4e5146f8cad5b389e4c0fa18260c96a193edbc8091a36 +TAG: b67082c21557b31392a9821fbce4b93706f96856d2581c92e7fb65dd2166624f + +KEY: a145adafac46280e1cee8696903c5f3866540f27f17a519637373d95dca4ac5ac0bfd85ca6e1f8df8ae3fcfc9158421581669db52c20a3e19c5d251952f63218 +NONCE: 90bd43611f235ff225b23208 +IN: cbe5f3a5b7a94b8665cac1a4d173a225679e1a3926d8596b5adc0ef4fd00f7d93a432ff141cc04f877be60b6a17fff40ac845a91bcee3b483862f67d9a76ef498ce5e49c361bfc018e401aff47b397e96b2982d4fdcd043ca09905be9634e83dc22a667c955bc992ec96ca1b76f73631767f64fc7151284d5aa81c1aa42eb3aa +AD: +CT: 604f718dbce17dfca1fc5e0f400151cb65bea9d7d8f26d56687a76a23f89201aab01ef928006d15493f5b1501bb99c517cf123acd956ab575e687298488a88d5739c266e67ca6a20a5dbe5f5f27ac778816f04e7b1764cb716477f3aa01482cb6b25fe034ab5d942013164aa124608cacf13d6cc9487446cfba54315fc6bfc42 +TAG: 8e3e1a01945bfd9e1aa4eff1cdd0a6da6d8fdd5446e6d732a673effe8e44d76a + +KEY: 63ac8e2561341587bc066c87cd23f7f33e6023bdc1521a91d6ce63d3ab213825d95d674928b56da1741aad8e85a8b703239ad74e0304ad555eeadebf4ae30aa6 +NONCE: 4f3073c3b780ebb146e136c7 +IN: 7f9a05b1aead29b4d5361c2606e5db8a48122858842679cd46f8386ef9359f998cd2c6c266791429624ff634a160d08faf1523b650c30b2fcd71517da5f377000251ef23cfd2510a0630215ad45fa6d2313f9add040a07df8259b82d3f29cf1ab8477cd114c9ee579d3e2ce60c5da2f3375b68b4d6e0913d39dac9399c00bd32 +AD: 22 +CT: d4ed811c8db932348e0c311e9278ef22f22cec8af88b3ac0cef77f13bbd9b8cca037c1ea87590a0ce3f3e7b3ffe1dcc4c7cd9e721baa5f126a3e0afb26dcfa02bf44428846c0f1e07ba0e026c23a39877de1e69e16a2766ff4fa3d4e8d3a97ba28f407f459ae3520dd840e8f9e149ea582048dc6e3d0227bd86a9c26ddd59895 +TAG: 0abc9111229bcb725953d139a2dcb1aa0cb9d3d6c01ef4733482dc5edcc88958 + +KEY: 355454fbe12f125edbc13550a7494f37efbe12b843058d29f892e1524289c2868ef0050a75a232d3083c381289e4950e352d68d64bf05f0608d694763c36641c +NONCE: 0a344bb3da1c4260f2daf256 +IN: 362e97f8ef09f30e5db2f21d40568d347d9bc42d4c94a563484b12eb109886ccfd2c61c40dfe93eb836bb6aa4f828e77c137485da2df494cbeb6a9a0192c3777b4d7a927fba11a8eaf604b85a81ac4719ce8b595a74656286fd0b80d1ad3f3393e6038b258af97af9a77f6760d486d9caf5a451ba26dee51bda0f76d75bfc26e +AD: c7c2e8196f37185b44515480d5d9451d79d07df4c1256bff6382f942727ce9b3a4f81ae964d8af2cd9f638 +CT: 32a67922947fd6b1c1bfaf3e1d41397173b97095e55307cae1c574daca275778d4aa4313fb1fe5b3997ff18800903ce044c7d0976abbb03b6cc1f7498d8b56d00672bd74f7cb152b677c632ef7a6f6fc13e95e82b6e35d663eb47f27c229c81174fd7c62c94c414e47216af2580fe822643e54907af77ae18e903fe856a02173 +TAG: 72d0fe5baee8090c5f8e79890b77f6d72a4213a7d1a81e0d1f1c9e6731e44d54 + +KEY: 664478c9d30d2cbc39351ec3b3494f3edb81e32e48bd4ef05969da07e770e4181a9ada3b2f83b46f40fc2d9ad35fd8ee6864ff3d70436d6cca3f8e0563cc3b06 +NONCE: 7313df9679181ffad2972a6b +IN: 142f073f2ce443c68822f120b5009e39bea3453017dc04c1b091adfddcb2a7e361c2b79eab1bf0818bc86e9d7964834d3775698b56a11ee07a0c9c03cb7bb895bf1a1dde3975c3662d233052824f1539f58cd6ad5cadb58fecaf2b34935ff711c45a639d642fb8fc3a52929b1296683bb13e67f2cc8ed9090126cdf28a4395c6 +AD: d0d78b94505793af546912f3780699dd72e288c775bfc75da6e306defcd868f6d40c6d6ce34fab9c11574ef5 +CT: cb913e40ea5dfe76beae612e9732d23ce352789987134822b2324db585179bf90d0ee20bee102e93a49a55fc978d19e99ba316cf8d9a10d2f2bcb75da4b135d1fcb8057edc33a180586015d8829a128f8fdc87b72497016c280f54f4d974c2c7e9d32ae137eaa1bcb670be237269fa73c3a0f273da9e70d89600ae7c231fc9d4 +TAG: dcc158c254ff7e131ad854a2158d51c643c281dfd7df342d5481384ab236a685 + +KEY: 409d1b4e1c187c8b1c053e999f2af648583e1045d56d553cce9270d08c5643ef365eb35e3bdeaedcd164b0122ad185e71c75146a9807104d9b65b56d9bc1dc55 +NONCE: 1cce3f08a5aa5824d063a6f2 +IN: a255239e4065f3effe6aa5e88814d516236d016c51cd8eb35af7cee86418966559802f8ff7ac39c6a45acc1f1b18cc28d7cc32ae66dff43289fe44c3a2a72fbadf3a7249d76c1ba9671dfc420ddf513539f2da5f31030f2b6775c57432c2c3486621d841e80dd4894229debc12ef47d74716838f2d807e208f0fdaf733bce76e +AD: 8f34f8b676e71844841c6a7b63fef1ad3061f2449c1044e1a281595da2d9e9fd141aea7350bd8cf9774d375e67 +CT: 969fc2c64261db415e51eee8cc5e0cf5185b8e3325dea516a70e32115a5b72233a44458c40f2daff3594d71e42ca2e3fc1c444ce171d22ef40009d798456613fa4b76beaa6d469e235997a302ac468c8bcfb8ef5de5cda58d7e554a9eab6cb568945dc37f28b0dbd674c083dfbd2e42fda1b42d0c1966e9652a21b32af71e2d5 +TAG: fa0789a83c255412501944a67bdceaff3f01d9a23b0c749be38abc956e2acae6 + +KEY: e6fd8144cdb305bf9e62a2c901764c62902f354409d8c5b9c8cbfc0ba8ac7d0859ff8994e573e46784395d89c355a91a313f601b56e86ed3fd10ba428a5481ce +NONCE: bae080718d3e5c5998542f15 +IN: 2258ffcd6fcf91b1723f8db0047525d61cc8ffc440acf3290690685d16384292493807312b7dfc23ac9d9c3ee1405baab21a3770a05875cfe325268b65fc877463e3208c842ea4a32cf144cc46d57afd91f6b6b5d85fb2dedb0702f0c4e7f742cf4c9b4aec02f07267ec1f7b96a5a3ef25f6c1b4c27bd829e86583e239cd854b +AD: 51ae57749b7757718aef9b9c47da5794659516e7f98bc80e6c18c89253f8617963331f54d4f009f087d1d2bd69a083f3a4b98f2a51ce24ffc6079774f7c7b01638b6131bfccebe21fea67bc839c259a50fcc0a16a69ada3c5adee4097d9e053a03266cb9b4b39ee2a465ec1aa058e61a0b9888b93bfcfd103f91ca3a7b274a10 +CT: 5b2fe8eea3313cc04d5ec75d75d05b3242b6e3b65c6fa1761716780c9529ff8ca523096dd037c5bda27984aa93c702ce9c01c63569a90657cc6373ad5d4473028b7eef69dd79c44c38d0063e8a8b7f1aa2bf6b646711ecd4eea3fa27408e089d9c4c4aceedff29a25baa6a9069eb7eac83a53212c0b387d700547c46cdc525e3 +TAG: 60319de093aec5c0bb8d5f17e950b0f4df0dfd20ad96490f6f12db461b2a4a84 + diff --git a/external/boringssl/crypto/cipher/test/aes_256_gcm_tests.txt b/external/boringssl/crypto/cipher/test/aes_256_gcm_tests.txt new file mode 100644 index 0000000000..30fd422d80 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_gcm_tests.txt @@ -0,0 +1,466 @@ +# The AES-256-GCM test cases from cipher_tests.txt have been merged into this +# file. + +KEY: e5ac4a32c67e425ac4b143c83c6f161312a97d88d634afdf9f4da5bd35223f01 +NONCE: 5bf11a0951f0bfc7ea5c9e58 +IN: +AD: +CT: +TAG: d7cba289d6d19a5af45dc13857016bac + +KEY: 73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a +NONCE: a330a184fc245812f4820caa +IN: f0535fe211 +AD: e91428be04 +CT: e9b8a896da +TAG: 9115ed79f26a030c14947b3e454db9e7 + +KEY: 80e2e561886eb2a953cf923aaac1653ed2db0111ee62e09cb20d9e2652bd3476 +NONCE: 5daf201589654da8884c3c68 +IN: 96669d2d3542a4d49c7c +AD: e51e5bce7cbceb660399 +CT: 4521953e7d39497e4563 +TAG: 2083e3c0d84d663066bbe2961b08dcf7 + +KEY: 881cca012ef9d6f1241b88e4364084d8c95470c6022e59b62732a1afcc02e657 +NONCE: 172ec639be736062bba5c32f +IN: 8ed8ef4c09360ef70bb22c716554ef +AD: 98c115f2c3bbe22e3a0c562e8e67ff +CT: 06a761987a7eb0e57a31979043747d +TAG: cf07239b9d40a759e0f4f8ef088f016a + +KEY: a6efd2e2b0056d0f955e008ca88ca59fb21a8f5fc0e9aa6d730fbfc5a28b5f90 +NONCE: f6775dca7cd8674c16fdb4ee +IN: 5dc495d949f4b2c8a709092b120ac8078cdfd104 +AD: 86a597f5e2c398fff963fcfe126eae1bc13f097f +CT: 04416e23586ee364b1cf3fb75405f8ef28fddbde +TAG: e7b9d5ecb2cf30162a28c8f645f62f87 + +KEY: 8d6ed9a6d410989e3bd37874edb5a89f9ab355fa395967dcbbfa216ec9ce3f45 +NONCE: 55debbb289b9439eb47834ab +IN: 52939c7416220822a77435a46687f134cebc70a2f1a4c33d37 +AD: 7790af913d84a04c1b72d4484ea2e09fdaa802d8b1733b8470 +CT: d7bddae8929ed6bbc9ac077e2415d9fbafae4a0432f8f7eb6b +TAG: e6383b16ed9c32521dcaeef3a7b9b67f + +KEY: 525429d45a66b9d860c83860111cc65324ab91ff77938bbc30a654220bb3e526 +NONCE: 31535d82b9b46f5ad75a1629 +IN: 677eca74660499acf2e2fd6c7800fd6da2d0273a31906a691205b5765b85 +AD: 513bc218acee89848e73ab108401bfc4f9c2aa70310a4e543644c37dd2f3 +CT: f1e6032ee3ce224b2e8f17f91055c81a480398e07fd9366ad69d84dca712 +TAG: e39da5658f1d2994a529646d692c55d8 + +KEY: 630b506aa4b15c555cf279dc4a7ee9add213219d2c68163ceaeda903fb892c30 +NONCE: 79eca200a5cdf92b28be5a7a +IN: b12e6f1f8160cd65278c48f68ad53c8c82fd17c2c39bbb109f077c17fdcb8a0b3a5dbf +AD: 46cb18593b3b26ba75e4cb20a252caef31d00be31093d2369e93572a393d650c68313f +CT: 9a9ad1f78b4d411afe450d2e46347a7df98f39daa4fd478b9ab6e6b417878bcd52743a +TAG: 55453a003b021c8a247379cdc4fa6da6 + +KEY: d10bb6641e9ba0a3f1b016317831ad4232f81c2137adac0940ecd7fa36de0563 +NONCE: 99c922d37c95ebeda8e81ae8 +IN: 8b9089df5bb048cebbe709cb61e178ec768515a0031288d95b7cc4dfffeb51b836e126a237ec50cc +AD: f1cbf6c83493b2087d9f88e02121a114f45ed51817e46ffc0b66a783350eae89c6700db3f3be5f4a +CT: 8a838c51a8ef8134481e9951033295ae686624aa4df72f869d140980347a5e69a6d7cb3d7119b303 +TAG: 9152bef766579a3e9a1e36abd7ebb64c + +KEY: ca665229adcc7554f1b1c8f50e7444c6d4059c525f9c0da1406ffb35d50cae97 +NONCE: 8e2df19123ce0ad41df416d4 +IN: 12365eaac86b270e9c61b3ae7702a6f3583ef4accb80a98454c56e34e2ab97d8afa23ddee34e7e3a522497f985 +AD: bf539d8e9e3a02f3e5834970e7efd40cc7cb340a075041428d6a69ed9fa5105e4bc63720be9a7040ce5b4af6e1 +CT: 96027efdcd4433df8e7f6181c05be365cdce550b09d45cfc96fe258eab6d55976a9306a0070c9589ef08cf7a42 +TAG: ec9fb5e79cdf8ad4c8a79c900975159d + +KEY: 5033338bf7526cca0425f4a620424662ebc58364c8d985d130e525fd1f598f3f +NONCE: b40842b30758aa3eef7cda62 +IN: 69a62b8c5f9b81cebee3a9345f4e49ea089b0d9c1cc57b4ef707956d0287de83fcca6d8f5270a9393e00693075028189bda7 +AD: 3efe0ed6fbafa61070388abc59c0d06589309736b02418df5534c8c594d61a2afefbee17af8283d01634b6ca3e8e2aeadff8 +CT: d6184677a21978b6443d99d7de1fd01c6b6334cf01b7e7d58456267453f4de96708b62301172c8c87e970f91c5301e0ff61e +TAG: f8ac7aef208712845d137b8b176c89f1 + +KEY: f33c39140999a2cb69e43129cb5df18fffeb3513ec3560792e9909784daee43b +NONCE: 70608463f1dfabb1fc4451e9 +IN: e2802c4d290468177fdb031a717345753cd7c3028ed07dea428db84e7c50c3eb7b24f7381a167b4ee31bf88dcaf5251fdb90ecbb74ac2f +AD: 10a6f463dc59d4791b3c2b4c93cbe2dec579a154962cb2c4cc77664e8c2b106c574fe115fd43dad94b8b1bf2f74820e28435b4444b2b82 +CT: a27419a46037323c033d7cf2a716777fedc02a5ddd8bfbdbca82ffbdea3037bc1cc80df7c5e502b32276ae88ad6fd0f0cfe72604648812 +TAG: b1ae330d47fd399aaaa687e141e23fc7 + +KEY: 2121056225a7b2316a93c4bfeb970486fa9c586c14ba8b40be5844a31e9449c0 +NONCE: b4b7d1e8fa7d0e2334c92315 +IN: 2038e2c6cdf5282f081292448f8febbb60a1520fa3771cbfef387f48c5915a1438ab709628e8d4c81623ddbc2f6f159c3c9a8922905c4994269898b8 +AD: b07f66508a39c4932b04c16172d6462d78273cd9463e52284bb73e3b8b8e7047bdf10c5ace1f903e5a5eacbf67c9351f82c74bda140df2fe0480c80a +CT: 7b54618ae09b37ee72e51873c82cdd20b6dca37c334af89548f52f34df3a757e632cc0d453fc97270898eb50ce2f2a98c4cbd4cbb22a5b7c7564406b +TAG: de3a9e2aab2439675c4f7f0b61216d5a + +KEY: efb15235bc91771aa32d51472877b0eb364de2f88766908eebc6e6b57a702099 +NONCE: 1a510b42dc20d1d0fb34fb52 +IN: 4eff604dd4bba67f143dab0728b8597e269d4e0ecb4ce80c9850afc645d96da239d9db360605bb4268d74e1fe3431a44242ae862fa2340c076db13315f615b85f0 +AD: e8dad34f727e77444a96cf06425640f1fc80fe3b01dafd1d91476140afe8204286d01b0ebdadc0270a3d218516ff5f08a69a7ba251ac325983caccbe0d9e1de359 +CT: 989fef0145e2fe93b9f99fd90123632d83d9df8f37d8e1f80dac329dbe0c214c2191009e31232538fec63a29665f0fc1c77dc86b2f5f2050b86b3ae48e85d63116 +TAG: 6816304faeb45da4e4772f5c35730f8a + +KEY: 998c22912d5687fc3faac262a902783fcb0c738520b5c4135a8dd2cdbd7b0dfb +NONCE: eeb535c5bd6edfd696655b60 +IN: 1f6ae10d425923c882b7d2f556571acfc10333ec665b07bfad9f8948a3b8c5e5f163a4e99d4726da1a35359c657c848f327b7fd9b5f61987440ab12b9399db24715715a2d1c8 +AD: 9a3c76dbaeb69a6481a89318caeb6358267ef51a1a364a48387bf77526837c9c70afb6f105cd47d2b976dbda7d2b6bfea7b76b135810c53437472f7b80ffc8ce4dc95c7e5045 +CT: 87f4e2c80a4f15f92a8e94f468e70fe7f0e0f83c0a7799a1d465043d25210ac6f0f39a5e9765b4daca637864d1bcc090d2ef33ddfccded2d2dad61dab443b3cfcc683147c490 +TAG: 0744d928a5b5ec95f3087cc2623f0031 + +KEY: e12effa8da2c90a5d35d257c07d1b467991bd5f75fecd7129aea4e26b9e27ff1 +NONCE: 4edd0b4cc349d37eb77f5576 +IN: 21dc87984edca46a629ed95ffb04471397da8806c525a781d9a71818422e344e4af577f38e7cdbc556d4766770a9a3c95bea59ad497fe0127816ec4dcecb6b999486719b0b86cdb2c9d09e +AD: bc158e6570fb0a08d73367dba65b80a8c8e57ba6c7b99493ebdaef0424e18d8ab1f7c88670cf51c4d91b77eb9ce0f89a46ed1316141e4299ec6c3d6e712ec9e92d3db44640402aa4ac00ba +CT: 07ab8c623d683ff83030392e2864edd4b8e3d296d60579a226a8d2aff6bc5af3c4598a18cc1e8d7db4ac8eb56a082af864ac52a324851dd29af51a0945cee4bf303ea111b9b627aabf5ff8 +TAG: 53e69b7be969c39560c016c6bc1aa4e1 + +KEY: 3d9723c9235939df8647529b7e4a57b8536476d5b71b424e2c27ba4d0b82b0e8 +NONCE: 60163d2eb7822af7fad64c04 +IN: b44face0f45e4a8da19aa0c5cbe3aa960ed6b74fe3d3d9201f52523dfe7651756b2ce482e759c87bde4ec670a0e808fb4883e437c7cbcf2f6470352174327824200cb0897edc4def1736f51e229addaa +AD: a4b2b7bf36a70a5246feee52c474058100bc618fb0e3d32e8c1f76153edec47fab3045dcc7eed9ca1886bb2593703c9ffb8883c45386d2f4e3fbb0b7c722d19f2eca94767174d9127450549e8993ae33 +CT: 66fa63ded066ac67bf218af7bc21169a875f4bd695f44fbdff906f0a9b8a067be721fd260571c53a8b51661c8d49fe178dcb28c31deb3fa71b096b387f9fc8f3657d280404c05d2b6443eba7e60b562e +TAG: 59d5450872510c4bfb590d9497524331 + +KEY: 75b0a20935c4a5e2126ac7420d632bfda8d41bc947c2402bed4759b6e617ff92 +NONCE: 0c3edf0dcd1125d7e263b897 +IN: 8edc98e70030e40bea1548f6f56b4561272be0c333f3b7ae53ff3e27c35a91b1aa42d39e6305ec4811e75931e5cae2261d88a6f7d6c5b05bfb48802264e9cac782411f1de579e29d464ba56840b126a3fad07f01c4 +AD: 7e35081ef652424da6304852243ce43ff711da17f7881d5e0433b1ad7535e755a8531b93d67ce99ffe66e59fbb24f6b42655524b39f2c84daa5cdacb5e7916266c05711a118b2128930b95de83ff1a67e53337474a +CT: 858dc74dbec6fdbe4ef15a3596ff7201c8f4fcca765bf5452f678b1493a66ed9852a6fa174a73099acf951a35699f33289ec50625538c01eaa456dc658013a29e4d133b856eb969c1f221f99e11fadc98b0ee08243 +TAG: 3d8f17838c4fc69f04d7e2b76eebbc0b + +KEY: 7a3823191abcebadb7970d1b65c2a8dab8a908151737bd5400b3b6c0d59e3b08 +NONCE: e32eb00e5106097e2ef0e8ba +IN: 220db5400dce604adee4cb698cdc02d2ca61622bbdeebe347b0bfef55cc45319b940f93773a9878725c5f55485d7a26363251b9ce0d3da1f8f6e34ad5329dc9f752ec7dc12b2d259ac89a8059085996a431a56cc2dc2400a26b4 +AD: a83b6dc78931cb7500eddcf77792e810c1edbd5f4e33f85018807a8539a3cace094fb794fa9ea058e82c830d42d5a6b3e22b7785698774aec5c73edd92731c51106a23c569c0c0fef18d13da1562a9a42aa435b243c4fbc9fe42 +CT: 5ce6ec0e1d67ced5a6aa46c909b9b8907b372be03331dd0940ceb6d87e928c14a1a1e8ef9096c9b63ab4cd93242ec7be7e38b80643f9c52e7e90ffa06b8f2d238fa63dcd97af74ae37802d124623b8a272e68ca18b3432b7c017 +TAG: e21c61d604253bc5b5d58283756b9eb3 + +KEY: 53ff6dc0af3e89fc2de7370caa433f539d068609fcfed6400a5b9fda4c83e3aa +NONCE: 91a824c5e023283959858062 +IN: fc23e07b4018460279f8392e86423ecfe465b25b60382f58995ef5fa1f9ca235e4bf87112554aa0e72836831d7b5f39125df11518b8aeb1809d804419beb05ae013482213012e4ce980ddd1c58e11608b775d12b450ecace83e678c69d2c5d +AD: b3a1db2d467780480f166859e0e7aab212738b85e88237c2782496c9c503347de02f3dad6bfc671fda71a04ff1e4661767c11303daa0c36d944346d39e3e29ec63d695cdcd83b2b57181582c5ac692b13e4299ab5e86c59d09c2dc6194ebe9 +CT: 88af588ec33bdac2cc748a01ee3eec97e5bbfdf69de1d66176f42b66383bbffa8b185cdedc25b11a62237d334d68120fccfd68c2f9447b3b8e1f623f33f7f97ad8815d29bf11bc0c65641ba8fca4a087783f4694fb1d574450191825f84402 +TAG: 2c4973323e635a885f78ee106eddf19e + +KEY: ca2b4d335598f26d3d3607e62b9ef853d3543e741350f92f3050894721d3d450 +NONCE: 2431b5cee8c3ecec4caad278 +IN: 75e29e46350d1fa99403b1e5baa414e41a8e714910f313f8e850cf3076508ff650011af766b51283fbd5626166d775fd4b4cb7124d26d77b41eb17bf642bf67a34c1caf0fa9b43eec12103f864e56c5ccdc81b89c1a35e394362688d05dd94eda3d05dd2 +AD: 31c3ce532bc1bae65b5ced69449129b112019cc6078268b853dd17c41832ecae07f9c6b068ef6cba2b55f352904afd6096ff8432081aed408d9340c319fd8e2029c389b6e3a4bdc38853444c3f7be9385ff1ca27e59c43b542e99799bb4ce56b8e26d6c1 +CT: 90c13ec26d01b7b96bdd6816d3ee57df57efeabdb15ba602229ff71d71793fe8081eb1b462e8b2967bc4af96fd6dc72cee3d2b6495c7f04c9068b2ad0b073e11cd5999df541ad705c6315eefa8da49c5dbc258f7ba922908489c1ce672971c3bfb6e8482 +TAG: 3a7741a094be92b838850c32e4b06c6d + +KEY: 49fbbdb5ae21cd955be7f7603cb8563ea0b02b77a9ea14016baa5cffc55d20c9 +NONCE: c0a4463350506d2af9e35d8f +IN: f31003aaf5d8fd6261c01c5bb1e7bf6af248e0be3cf8aac67ccaeb0b7468a40d98be526a8e4f692dd23763563e601915ebcb59ecbf03bf9c665c4c5313c318939a911888fd427d5297b9b2fd91dd33eb7ed38e2f0f6ab74ec263989cdd9915811a022d4a46ed35eef0 +AD: 17e01af2386531ce67d5bc3325d8f83b53a87b38f1c305f99c0798380a7e59d3ecddf33a5ad23a82e33f0fa34eb2438b17e958451439774ab642fafd3794f80a0ee1b9bc165f32df705a6175310670ba54af3a204e446db35170ab02670086c47a475c22d1f14cbe44 +CT: bd661836d1b74244baca62d7d1cb6717e17e2fb0bcbc8d36b3265a983d557c562b0be60708499d0e7e9626825bc049db79a0ef4d2393fef6024d849089455e55693fd4da3d910eac11496492a645e4376855732765e1b3580461a2a2533cebb482736ac928cba175bb +TAG: 4596e3802109c899f27f6cfcbdceac5d + +KEY: 30d0e4f6425e38c92ac34dcaa06a815166f301289ca9cb0ed08156617d87bdf4 +NONCE: 525618ac9e317405c7d44367 +IN: 06f2204ca864dd3f7c9d0290f6fe3d0337eb9442cd5d2b586d1d5c30e58951fc2f4e99831ac7bca4356db4609a0428c482f2580b9e8cf5fd00d86d474fd88ac3b2413f44c1ff66e59e7538c090b2444396f02004ff636aca05ec40439f4e3f470a24916fa4033cb60127223addc1 +AD: 23c1a3e1083904f7226be7242027abb7af9d62f1115340cd4a57611be88303955cbcbeba44eab5488c80aed3e063c70cb7bbdd9ac289c8c8977868c3702be63d0358836838a97b31f6aee148f2b8615ad7c5dc0de7c48db7752e5f1ae8637f8c70335bbecf1313ae1b972ffb9442 +CT: afe3e71953bad46ad28113b7c8f2092fdebaeb81626bf94bd7e9dd59e000e8ba31c1ce7f728fe19dbbb42322e54aab278e3c29beb59b2d085e65cb8e54ea45d6a9fb1f561bac0bb74afe18cc8de51abf962c2fbc974c7ed54ccf2c063ff148b3e6cccdaa65cc89ab19fcd9cd0436 +TAG: e9f5edea1fdfc31cd5da693b50b72094 + +KEY: 661309741227606892db13ab553070b456c5e421cca59087144873ae6d59e590 +NONCE: 9f07692c017e1391a981e70e +IN: 40b5f8081b5dd173203e02e90a6c171fc41f804b2903ea18109edcf77c03dba687b47ca389c55389bd7b0ac59bfaefaf43b5f97065df6a5375c1fbb95d95cad589c2a45cd9e1e7960b1d13622440f7180aa565863b4f9dfe26ed336ff4318653e1a520bdb830e01db78a7e598f251834d0c9bb +AD: e8540d084f24b80414af554f470048b29a5af8adb2f9d55c9759e5ff1595ca74884af67027324587131d90c77ca72b2d15b66564549ce93df7f667d0218a6e874848563a33886c6a0c5a9d00fa435dfabaa9053243b4c8c25779a4dbf79eb4b8530a7c7bf4263ea824713a90cee92dec78c449 +CT: d543f49e6cbe26f1d8a6e058769d5b16e6f8255a28b4d73ba2cbdf664bbc5ded73f9dea12a11b86b6a6acd578f685afabc232dbe9ff8431a5318ec7f0202959a310595b147353a7ca89c9d1fc2d2b92ea610cf6d9ad2716df2dfed70f5b74d498edab114058c22c96873a2a64abc254c82af46 +TAG: 31a8441886d0e4c6bfcd6d74f6a5ee5e + +KEY: a248b0d683973d205ef2d3f86468cf5a343d6ad7c5aaac0b9b6b2a412eed3552 +NONCE: 8f62ffac4027f4dfeacf3df2 +IN: c2d7d29256832def577392acb9fe4f249eb4859025ea55cc0c4a67806caba3e1cb81bc7f5717d94e1c91ff06607b23c238daafcb0fa96905616f02205b702508970fe3bfca87270ed1102a9ab96df57ebdcfd86ef6e9c4c4242b4febd82b0220b0d6f76d8c2d0fba33ca49279907f6bcf7e8401d1419ed58 +AD: c738cdbde6dc277ab81dae20fbbb4a50d71bcf0ac1ee0ec6a39747ccd87be40b1f0f2c37f2c6b32ea99722979fcfddd0ddc2e4ff34a2e6113b591cbfda317c6f4b021ad30325276f8d8dd78f757618b53297fec091f029f9b00850b35f3863a3801c882422b318b4a1bdd89002f928371ea05c6fabcb1792 +CT: 7a837df292ad2e58f21b89da43a74de411e1746556fe47db55a136757513bd249384bf67887a5c1f605e7f7e3057596e17039701ea351e5ccaf0fd4882559e87197144632977cf07cf9e86784a959fa7399476a4fd196d7c507fe3876d759e2b37bd37edb3c12b89716f29ddc8b64974263a1ec1b6364b0e +TAG: 291098a2376a0faa5da6fb2606b4f2a4 + +KEY: 80634a8baea1c4fe5dedb664c9b5d714422dd1726d642e60d15e02364195206e +NONCE: 725ee5023ae08fece15d621a +IN: 4d1d8855b4d155e77bd1bf34b3d049ef09b2b94f4e604306406b015a2d520e8772b084ed668b868e32c7563085f2a82e7d99219da549e507aff9515e45a045c7cd5292c0e09a3a38c769acfd0a11826b27d8bf05184971670200e79c49754debbfc57d9ebc661b25f22f241c4d143bd922f7b0981a48c6a63462cb5cfd +AD: 12b3fa94a64454dc5b47433df1ce0a7dd5e8066d05b2433c6cbcb83087bb7d22d153a19c05aeb76141431c5f9801cb13531691655939c0c812611c6a30083ed3ec27e63e6868f186be559c48367a00b18085ffb8c7727638e833a7b907ff8465e3a01d654b52432767b18b855c05a9cfb5d4aabae19164f0dc2ca6346c +CT: 6b01e934916823f391cd0d2829c224a12eeddc79f18351d2484ef6cb5d492ec9ec4d8c4bd3354f01d538bbd81327f6360a7d157feee64b539489bfdd1be4d7f724d2a6dfa1af91e4108dbfffd529afa71388b07e5079236644da289ae236100b2fbeda0c17bf2a01e76cd1f88081682c2d074223fb8a41d59e70a37870 +TAG: 55762e95d897a33c4c75106449112986 + +KEY: 4f2edc967b11983f05ef5ee2a4364039ac02dbcccef3f3719913ae2719c8217c +NONCE: 255f8209b0c67a6277bdb42e +IN: f8217163bcaf77c1383089e396b271e22c517e8ccda244256cc39315fab7d0c291078d90e9b6e336992f015282caa1ec0ea858a179c9735b7a2f0d50f6f1eecaf3b9308772279ebb95f8aa53826e9dd60fb354de0c50c10001c98812b59d7c0f36daa1aecda6782ca36130fbb559363fe07704b0b91ea85be319ada027e47840c764 +AD: 1dc7065f1585384b88be47598ca484782716c78f49b3b6bf5d24a5b0d24fbd7831f18d77d80951d2c4fafb6f939d46362a69b558afadb3bb4d8aa27f7fcf3dd9624e1e075fce9bb239926d51ea9dff03619d64d5828103a414e360adcda8fd864fca55c21df86c76972c3765ab1d68ce89f708e7e5a3e06cd4de08573cf750c6f5f9 +CT: 6719849b7cea3f7f2a8e4de13d7a864d581b7c638f49fb06378a768d2034548179963c33f0ad099254c2edda9ef771daf5d299f58850033e2e449d7bc21ca3f7d3b7408429b596da615c8582886a6d8c1a9ba81fec4a41a38b7cbf1a80ee0ec8bd71451e727051fbf2a1d1e3c6ca98ee113e47650ba4fe80451e79b04abc8bb99a2a +TAG: 2ac7f962553a8007de3369c7795bc876 + +KEY: 51c5cf1f0c76ec96f4a5f9aa50a36185521f3ba259145ac6cb4da3cd12467696 +NONCE: c751e5e7e3d75874acfd2bfa +IN: fcda42cd098b7936f4bebaa37d5850cb0fdd6526966b1b5734f23d5050ee44466627576e1144957929123198e40b64eaef74476870afecd7b70f7583208603a1b5247074c6c77e10b9bbd41a3d468ff41db89895b0e9ca95be77526ddb30d4c5eb0796ba97d7d5c56d0eece344dde3ebd7de586226c00da224b04e74d9abe832686797df067c52 +AD: 343ae5e73fd1da48dce92ba7b86d21de0a203ba8587536fbaf4646bc45051a7feb343e38916f6c4c75b65f940045e830857c7b62b34a44622a36b34268b8a397892ed3e4de5df3fa7384d4ca50202b5b0833f921349c877931f4b735cec45db6b95410c8042ba49c1a39870276e0165f09c73b14bdf7f36d19084f958695c7ad2cc56f0487eae9 +CT: 04192659d6a2f1b7be472372c8f969a7de388c97d37b4a89653593e48b630947d2160b569379698e94de49b21572ef0b4dd330487a8be814a84e959a1a8e3cf33dcc9f7464fd44814d0cd7ab85e4c01c9d015f42ce3723c8ef8c311222b0c78eb83d81696c217992be725faf27701b4922c6e6099442787ddde2b7572500a5320a4d0c787b786e +TAG: 23c7a866574976dca8f401c4b5b58292 + +KEY: 1cec3efc0311d623f34b6853b3dc97e470fa728cdfd65993d9d48fdc192b28e9 +NONCE: 320fe742ef171b7b8cb615cc +IN: 722e503a97166a07974dcbf136fbaec6c03668fa52495b040383433ca59f6311103f2fc6a95ba4c925f8637167537321eff6949aa3051269fc094393a7b17d1ac8d29af052760835665b0ee89adda5dae7738656af9e8513c96e8a532a46ef34cd7430832d2be51c586a14e9aaec2458c1911bbc0f90b496737e838a12ff37d3db058bda9360d7d33e11629a +AD: fd5ccf6b6948c3eb96543aa40f107fafe94e5206c326dd8900ea510c6b61d1bcf746151a75404e31406c8e991fbf6e660db7c18e243fd2608aa22dd7ca9de88f277037661ce6dea4ff0a86809dbfe1708cd47d3061a34657cad143e6577549c9944e081f79c276300bb406378b26f349a91fa87de02a1405d712c516ae11b4bcf30ac9d56e677d03eb33e3be +CT: 363c1d6b806a6d97e2fddf53b242378e1d2b818828863fbb3f856f7737d63998a84e02d6c91e1df5f5eb6cf89f7ef53e16d10ad52f82362292d3acafaa02c23be7da7616a8b8daf8ee3ae74ee1078742c4ddc3e5a110e510417b9f43fbcbb00e17af3301b2fbcb784fb0a05b66469e771fbd78114fce3c4352c42928bf5a0ecc49228a3c930b0790bde7ad7b +TAG: 669482999be99149f9b723b60fec62d3 + +KEY: d3465cdecaecbf25943b7bbf8084ccabc15474a4228c46cbe652a99be24a861b +NONCE: 04fc836de3a1420b8e7136ca +IN: 81e0e984ce0a4074a44524f93e375eabc650a847a42393f5c524c65523368d38a7e2b677fe08502dd3bc42311775016b5689c660cc0ca8cb33a09b89f3ed3d02fa0fb75ca5bf0dc3c27c546b369ab5e7731f93bc074d37ee50d6f8366f6c8a45f73ac92b05c4aa552ecc5266041dc122a0df69a36ad625a26edb57bfff43a84e527ea0d9d3cf076f8de9eda28eb09de3ff +AD: e4adc14ac4bbf3ae7ec7d97f5c0e6090bf8127a75e8b70e9b86496a62a759dba5a4eef64a8c679c362785501260d29b58e1af647782564947950428dbf14edab8e6841c7afaf9e7949b560419c44bae30315c597f6f6e02204da7ec605a4d9a8753de1268bb0b1c84c972b4e7296da5c969781feeb35a44d2aef799ed228aa399ea04e21cf9f7d5600a2c07b047aa78388 +CT: d7995e7b610eede708526c05c584039d48b9b4356fc71b0c37ec2559309a688a7c69ac9655f94e178cd2311db58587863b0fbb990554dc9a6aa849571f945c61e5611ae7e1a96903be725a1aa75adc381b86e43fbc68a36f44e0e0cb8fe5c494caa91f758597b6ef3b80a879154cd8a7e5f570893b4f768105b24b58efb67c5f07c6db60e0f48eba9563f17d38aaf0847e +TAG: cc3fe61642c2d7fcbd579048fdfb19ec + +KEY: 1a0dfe2a6bc6a69659c68942ad0858e1df905890f47dab728ab9c73f742f469f +NONCE: f8f76b014116ba61392597de +IN: d93eead436e835a061ca061e3a53c3f9c66c6f011b21682b8a6fed098bde2018a2462aa5ab542c69bfa2805612cf6146c9150888b9720db1dcd0f359c1fa3416df4cd225dd0b0d949e917adfb3e83bf5ba2b967d48908e6b6d8aabc545335014d951a67390d7b5c7cd7dcbcf66e4e3f02aa4e5e9cccaf73e75622bad006c63433d36cb1c6aa4aa253dd1b2eacac75c548aa6648ecf9d +AD: 56ca2d5340629ca75de4e98921da352941559bd79f47ef0ab42d1d5857059352f96ee877f5458f090ca237e4eef5b08a53311c8dfd4c4582f18a93aaa8cf75080734cb2ea3389c9c74d2b04ead614eb54512ea93f0e3434e9a9366454b303a8129d6ce6cf96b1d6dd4f751311c736b517dcb50a6f6e0962c46637b4f5aaf0f34bff518cbd551a7aad3fa615708b17cf6d8fbc864f580 +CT: 8dc4d8483dc665b174ba32d6b6244da5f2a8fcc4b1865d662ec23057838b332a07ff073ecc893d413696f3fffc6dca5d107a5673f14abe8e0457a02e61138380d25e269686cbbd23cb7da3060f482f62bf80a40dcc2e711ecf5f7836ca14e456c4b73a48bef90749024393f5f8af01b73302e81bc37c4110dc26174702231d831cd14231905d2dd3f375cf2bef0425084d5b19f1039f +TAG: 825e7b7e195f65c454ce9fdd637138c1 + +KEY: 03cec87d0a947822493b5b67b918b5c6a6bbdebe45d016ec5cb6779c3ddfb35d +NONCE: eb7d261a6b56a179c88e88ad +IN: 2326102c58524326759ad399222c5b5a563cd01a29809d6aed4d49772a4723cfdf30c9f85f031063e838f543c201412d6f085a8f5435b0b2fe94659aaf70cf7bde99309239ed5b815b48342d4f81011f5aefe10ba105ac15601c64a91076c29c3cdafaa12bdd5706dd7305b48e923873cf06944b5027b210c59d79856f602bd6481980ea909152216756d77362c59d57673cedb91ee6f56a40061e +AD: 4d0fbeb69c1869d2d23198ec49b3dc23149005a84aace7025293c3afb8cb2e38c167a822e25c2fdf667d3677f4e94ed6574529c987de506d26b7ffccf3b7a36d9adac48bca76084710338eeb5bfca9df1bf6b403e33e90761a0b3152afac333071a5ef4f54010b945d03b51f123865673e8877f41ca23359e60518f076cc64232b306bd858634417e92e546ede4ac6231635c9cfcf43aab1f8fc1e +CT: 06746f993843901ce72f2fcd4af7d15e64b3102d2f9bec0fe72cdd0b97e43177a1a2238c9c1dfc3311f701196653249e767a73dbe819b660cee07a5f3bb8f25823875fb4b4d34a5a3a212d2e166311bbe11fb1d36f4e725c3b74054ed7fffb7082203ccb5e9d65873cb8a1ce28d5c6e2b6555c1a864a725e6c7d5555d37dcaf1d0884264be72d38cc4b65bc2f0d039d542c5055da56c57e084b804 +TAG: d36a4b6d2f592d4f0d347d906fc319cc + +KEY: 7f4b4bfa26719d9610c80ba3f474c43127f4aa3414fb070fc2f389e5219886e1 +NONCE: b144d4df961d4f1c25342d12 +IN: 638982b95d66ddb689b7b92e3adb683ac0ac19480148bac9db550be034cd18dbd10f2459c915e99c385cd8dc4dc6ec48b75f97e818030fc2d8fcdf66d66b80df64f0ca4af91bba83a74f3946b17af405bbbc6e216435641f5633ad3ee24c1a2ed1b39f649acce59ee56c282a3aebaee6e97f96b34cfc63d5b0482fec20d755f399dd5f61688fe55878713cc55d562c2d72236eb674a340d1a64932cdd8534a06 +AD: f2fe3d27bfc278cdcf16fffc541846d428b31534ec5cf51c30c8b6d988dc36cd6c0d41a4485a3f4469e92ea0fc7e694065bd8130c2854c95549630bd9cbaab2205f27a6efdc2c918c3be53f2d12f8f7cc8e6a81dc8be7cccd217be1fa2e6887cea7d637d2e2a390f50d2c5be10a32a9b380a400cddbdd40eac67f1fe9ba6033d4bfa88c563eaf57272c8a7052916cf4460f31ad026a0ac2588a45d082fbb5c0e +CT: 0d4de3489e09c7239972b675063579e409acbb663bea76bee8fb3f7e8785158ebe1c26db9219a9b97ea29e74762999518613249c3a87fbcd0128f651e2db8e2167f10ab532eced3464b56bcaa09780e5ece18182a6e092477ad933bd8de015c80e67c6802257a97a647fe2b1e9ab6a76c1cbf7d905deeb824aba2a34095f84b276d55ff940d6ab788c16cd63d9b16e0908d718c851a3230b0a37257751df5a38 +TAG: 9f0a882d4456847f44c7287c8ff3ba04 + +KEY: 9799ae8045d58250e4d9c3b0ccc8897a04b5b9fb164e54019dc58d7d77b65459 +NONCE: 0f20d002dbcd06528a23d5e0 +IN: 8f323018b1b636617c935791e1c8023f887da67974080af07378b533a7573424f1de9193c5d38f55e9af870f6c60ab49c80d7d1ad1f18f1a34893fd2892d49c315ee668c431f5f35e3f60ecfd534b4b09b64cc77cd16b0e1b8882872cd109a5ca377518e5b660d75052e9a4228e3935705b6bf6b4f4249346b7bf4afb891641a76621cd315cd75de391c898959be945ccca7a96073f2569f217617b08502f7d569bd2f80e0 +AD: 3f1e297bd91a276a4a4b613add617b0488414a57ede2ac75d10934e03be58ec518a418e98a4dbb39d2365889db7c5f389b2a16d8c702cf21b888a4cbf77b356df48a30298c825fb86128de45d7fa0e5f4b0b7bf82a2c4cad2470f33c231802263901fbda54a6edbf2df638716492157ec1407e7fc2eb6c663d9a215afbec3612778b8115e78a5fd68cf6ce66c12c0ca26e5c1f7ab079bc09c3bc7b673d21835671a13dd2a0 +CT: 9a5758dad7997a766db05d698b43fd491bdcec21352032cc023bcf10e136523219745a56f0360efee75a37de55da23cc7d8184a50ccebb110bcb960dcf6b25fe731e21f26290281d9c1c7715c4e6ff3dc0026cce52929163ba222f123d4f50e1d3cf67725fb4737f4010ee2b5b163ca6251c50efe05c5ab0b1ff57b97ffa24c98653f5c82690d40c791047a3d5e553a0142fa2f4346cfcd1c849a9647885c0daaac9efe222 +TAG: 5b85501a476217f100be680b2f5882cb + +KEY: a26c0e3864a7dd3b589d17a74a7c9c1f7e8f9adb4aafa0e75c083d10956b6bf6 +NONCE: b54a2a43ca3f84aef3824375 +IN: 6fd4ec60613646490791d82de30ded1a12e61fd270f1642d2221272dbb150ef63ef2604213e203b740dfc9c4bcdf722b3c85aa20abb1197949de710d7e8311956c8649524afc72a9bf5eddf0b284c7fc6d48a741b82c215a0dcd73bb8afd08d5532a6f7f99b5c6beb2ad793d6da53a81e6523b2240729924ddac996a723421f57125f928990daa7a55a5b6b53d7361d9728f66590d969659aacd9aa5c0ec627d991b55e9fd0bf9c3210f +AD: d6d8b570eca29a48a4d408d5b27ec6aec291d70cfefcd02bbfe8d8ba8aeb6db770bfd723d2c3a4859f1992767d24e7b33e3e241874292af640e2bd22a5b77e0e9e1e0d5e485041cac41d4694ac929ae1fbc08e7591e1cef689028f5db26f95fc9e0868887fb9c635579fc6335757697f63b4f2b46664ae338eafdd827988c8f2ebad80ea9787871ed8d6b302d5dbf7e8019f2e139c59036cb5964a3701ec049b839e19e33e68b83539c8 +CT: 2420e09adb24098038b2750c946551a5f6a5bdf23b126947348ddb5e938b3fcb874b33fbac6407095e05ce62df999e7234cd2b4e413009c71d855b23993cd58c1e26ba0deed891dc88f099fdf852cec0aab45f488a90edd8feb6f4c837036945bd304edbf7a2737921a2f8c1b00a1daaf9e25b908a65a8f69963fc767bc975b5b7bcc215ce37009009dc90b5c7edb1a1174a10ad28f4c1d1a2241e7ffc215edef4f847ceedf7b64f2d15 +TAG: 20521b35310385ae66557740b435d204 + +KEY: 53ef3dc7a10e435650dd20550cf3ec2b997afc8d9e79cca8f7062622afac3496 +NONCE: 257a205ed0f84016183f4613 +IN: 081e2769935f945419aa06fb5fa7d8412efd1f9b52a45863808022850836c1974d53d2b2c5c0cd420711a71e6d1a09e984366b8b677e6c61bbce8f3adf9f5a9fb5860887617a08c923171d681c4fbc6d569690f6a183d42b52a80ef0693862efd22bf83b7b4014a7008424c356b5022df1842309b3a4a2caee0fd3f4d3fc52a17d53959daccf8e0ca889578ee2905dd8c17d52e76712dc104344148e8184c82af8165ea8386f91de585b54fc8535c3 +AD: 5b73ae02bf4a70e57f5d48fbf45f85b8496ae8514c8aeb779c184f9cf823d8c1883c9e5a42b2c099d959c2298ace2d86c4479059256d6a4325e109fa4b6c4ce90f84a8228316e80aa86de9b5e111d88b2be447a29297b35ca90a8eb280d4c0fe92a1d593cb966cb0010bc06831efb0c72c1e222b031e900ef06ab8da542a5abe2870a0efbe92351d5915ab545b14900e41a27c5ca9d75d6277afafe7ae861131c2767eb314c0c3da5c264f8f2b4ac7 +CT: 20ecb6cda861b660656d692c626436227bd4ac17a9bc71f6c84a1917ef3b5a0f6ba370f00fa2e7f1bd5aa8d6c15032572090482c23e4ab7376ef1f4dfb77f79d5dc065792fe3476c9c37614e32f493e461981b519dd7d10234c2c69264ffe5be06a8e14c81022b652c8cfa24adcc7c7536a55a2fc41e9ffcd09e1c483541cba814eafd5e09e9e44477018a41b073e387c9257c07d97e40f0761fe295d015e1f2df5be65b13f34b6ef0fe1b109ad109 +TAG: c129ba4c10bc9e9c2b7d67f5f249d971 + +KEY: 15ddf0d794b1bf2e67db1af47b45b8abb0c62ff5fe09b29659f63ff943815c39 +NONCE: a6e6b4fd129bee3ab8144da1 +IN: 9c82ac83e3dd227d0cb9692703dbf41292fbaf4961e28b7407ef069e33850371ce2838b1808ec1f837511dae9899a867959183ef3d988ac20758d7a1a6859cedf687d8a42f3dd53fa4b5843e5be61422fb8774c9eb0fd22cbda5950155caa0ceaa00417f1e89a863fcc08cbf911776fbea8d7c14a6d819c070c9abe76a7f0d04598188d07fcbb822758081172e654c025703bb24c523cee2dfdc31c8d2c84534a60e7efa9f52f7e74e19c859889f9bd024f28763 +AD: 892bc04375e9ad5ad2b5c117d1aacc202a74ee4cd4125019f38ed4d716ce361b8b50463ec3255a00670f5f95d361e79349e90bfccbf084586cb5fa145b9eece8a10187c13055ba0d17c0fa526ba7985f00f3eb4a2cd53b6da488827fa8481cf47f6be58771d1e40125652732a7dd5adc49cf99ed6b085fa9fe8721c86f7241b6efb6002e65ae5f72e16ce6a09ce81365485b20f1fc2e092216024b1acd0bb4c2b4ffe28d62a9a813fcc389774688eedd76c0b041 +CT: e30465518e7dab44b9ca4ab6c86fd7b701e334b050a7889fefd08aa12c9e381acc7875ad5f8574fa44f8550bfc820b6d9a5600cfb82d1f98721a875610a91c8f47960ea64445c0e22fd3ebe94b3564e98b9b00a68e9bd941eef5382a67782c5e24ac44b928fc986c62a02fc702b145843b1c6882188dcbbb6f6b51ce1aa7784da03cbdc3efb1a01c1cfd7e90dc3332fc6e912a6a967ef1f239cfdc9752e235dfe75dab8088f8cc207a4a28994f122859aeb52d01 +TAG: 62e7455cd6b95319efa3ae0d14b88452 + +KEY: dc0cff51030582f29676482ec8dbf0490a135a4cf3e444edfb7d1ec733cdf7b9 +NONCE: 58c892d618ceb6027afbabb9 +IN: d6c4d49a9431d51bfda5bd4b07997690748fdc3df196d27d219a62480dfcb6300c5a234d675aec1239280446cc134bd4e0e0b5ebf6f10bb11b788caf949c0c3553497b62e729f08700b66c6720c35f1f434f16b15a4e404d627fd054ae1394a77d5ba728f3422aad5d99a608c2aa52b058946a76a408c5dfb210d280629ac999e86ab1f9da8f2b7b79ec07cb666105582564974180ace98c63bdb962e4580692abe58929d29f066d2f7e25c23a3824483d9e49cb6f5fc4a1b0 +AD: ee3bc8d875a4d43c278cfeefed8ced8a3da946adaef93dc356001da151010548990fe08b62edda46634db320601c7f4b50956e29868bda9ae5df186f15c3ab4a19d7cec274209cecc71602e45c37c273b7e4b2a168de5c29278042a3dd1fbea0998d7d9707d412f476ac8de7936e2e5c268a2f22646f682e664e526f88004e7c461bd42337dd21b1cb39ff678974adb67c2ea1b7055ca98697ec16c4b3bfa95b4dcbd7fb015480135634c34acb20f58549f7e7e11e20a991a1 +CT: 54eedf8ca21f31d21067af5a05dc3cb99c3dc046540d2cd1664abb32fc7714ac057d039cebdeb124e1ca9511bc71f92ddfd4c6bd3edc8a1934f2fa2511503944f2a0818e30b9bdd26bd3c51b9673f55ad3f2ee5e41de114ccc55abcdce06a5bcf63a5bd61fe71dbbfc97e1c7f3417fcb9c1462e244ad91725081c9176a0b91d3485400d273a16eecd870ec1e9e016a7f4af2fab39a0bc93576ffd1eeef9cc15b7e47feaef85b21de422666ec722cbaef26edd1941e7dc03f72 +TAG: 1cc8c395b2ccae3a685183667ee7bd34 + +KEY: 90da49f8f64e8a585697a43644a48bcbef33a8ed23c1a93c65e59a217c04a1e0 +NONCE: 0812f87792508dee6868d454 +IN: 26dac57d9f30bae5831f98ed074cbc9af9731a52b2322cdd23f1f0abbf78092c48d6d24a43c7d49edb3fa66086030f37dd9dc67847714437b11577d2bec645b3210baa8f7a540cbfc20deec5973b7489b7607eafe72e249df5d0fed95e29f03cf7f0c7a22fb2f06a0bc75214446b06d25a45ab8087270eec56af3960f53b80412a4ea7b45e54a2c374e8a3789e8eb57e656e22107503920313ee3e4025836b9e1a98541446c23bd5674cb83483642f2f3e8270bd1f77c85bcfb205a9133c +AD: f2168cef97c27a902d93cbca07b03f35c5c3ed934192d29a743c3a6c480c5a62172c088fc89cb2d8651b8979e5bd1864272ff179be8003c6dee18789c17583dc1de4e8b4fec80e5c7575838e621cac4b5b51ce5952f22e06b1c196101d2ac8d05e797323e5baacc49d1e74db97142e1bed723d46ab858d59fd36d5d08eaa63f696b610eebdc9662e504992fd3481de1264bcac8ac426b09fbc641ebc93f72c5d460088fe0b08420d88fae219b6a5a67420a5f9d1201bf8d64b2ab3e9050a +CT: 82196d89624689bb172e4ff71619046a91149c8ea99ebbaa3f2c32c77938b5ac466481575dd82a008c7f5867bc46ee44faf95fa40b6237c8c3b62474af2efcf07c771e23a63e65b48b0bd8ed26fc64dffe03e71fac6d3857b1248df63d888567d7d3618c68d6b8f1c88029bd7af8677d3b51f70ccccb4eec9e100768515637ad8a4b2e2e317902e456974ce9fe23095cc68566e85cd913e8b64119444f124640d16ef3e98136f32d618eef78f7ffbafb64227b3185bda8f541c0e7ee8405 +TAG: 71fffdbd6358f755dd22f1dbe42c4aca + +KEY: 0b1b256665284390a9193b7b7aa4e3ad15a3d2a58e79d75da8ec284c02fa3a2f +NONCE: 346ae65660de8920605fe8d1 +IN: acfa83f56f137ac39d6447d98c5f7d5e812d1d8e7c7fa7f7beea9a87c59961449683fcf5332c9ef1587135030309a1c2d95257114b790b18cc32f65f4c7d1652c0106e3331f826e9b8b0dffc50aa6723d0827076b71c668370ddc8156db3831559a72e48266b3886a6d88318e6ca646ff561ed4f71e665abb7a60089f0a115c7b7fad9cbba6c4cb0c242b9e1f17705825d98f4bc10bacd8ab2e11cf579f29b2a0b085d8c96a372434785856b483c3fc9ae909029b0c931098d7e59f233cb6450fe0b0d +AD: 64347fc132379d39cf142ca81d7e49c010f54f354ca3365d5195a7e43175c9a47603062c5ca61aaf2b381f5cd538bbf48f50d620ff2b5980c086049a378aca69570ab7c406b510a6aa6b7e8682ade6a091b1f822a97ce671fcf7c911c43c4795b78ce1c86e990e32bc5c9fa34a8a4b22a20d6f7c46722d1bafd49443b4da9634db4615f7cabc3d5bd9a8921e67de45dac261f54bcd0af2b2f845e255a16f2d2f1ffe26e88238f5dbdbe111393aab3409e08dee8b9bc85c51b385c191ee9290454236ab +CT: 9d7421330f0c2a525495bc360cd5c2273531d050d461336a254c9af8611d07c3559931cd6804fbdc6e6c9c997283cf40bc23596efd1bf116fffcc6620e45d1c738569af012a7ed0d575ace3c12662f88f3ee480af30ee015ae70db112bf4a185e220660a912f9ad840346e7cc0715e853dcd9b415ca9e865d5e4de2321e6a1b7cd8a35c760abd3f099d395576a91503147bdd51cb4bd1452c4043b42dd526de6f61bcbe819cfa3c122c6f62e0d4c38b443f5a138325a5f0ff8a9a2071c2773ce62edda +TAG: 2af508d74bcf8157ae9c55b28b5d2db9 + +KEY: c055bfc7828d9fe8fa8d9851d33f3e4888e0f7e286e1eed455e14832369f26fa +NONCE: 2804e5ec079eada8bb3946e4 +IN: a26a9b189ada0ccafab92a79711360c7c396374c6170de395bd8ed80dc5db96ef1534adc4dcd419fdf1801add1444a195367213e374eb1ab093f1f54cd82eaba5c1cde6b867e0d8fff99cdab4d96e69aee0c58a64120ce0cfd923f15cdf65076a12e06e53ab37463096d9ccb11ec654e401c24309fda7afa45ee26e5e4b8adc8febbddaff1e7cecacad1d825a6b16a115287b4b3c9f8a29b30fa6236ca6e883abda412177af38b93e0e64b012d33d7bf52ed18c4219bdf07f36151b7ea4c53091ddfe58b6c9beeca +AD: a184e4811d5565849a08d0b312f009143ac954d426ca8d563ad47550688c82dbddc1edbdea672f3a94a3c145676de66085ded7bcf356c5b7e798f5ab3bb3a11bd63c485fbcded50c3b31f914d020840cbc936c24e0b3245fead8c2f0f3e10b165d5f9c3f6be8f8d9e99b97efda5c6722051d5b81a343a7d107e30d9319c94dbc7c31c23b06a4ae948f276d0eabd050394c05781712b879317ac03eb7752462f048bcd0dccb5440f6740ad0a3a4c742c3da32a49dfda82ed1b66380a8cfd09dda73178ffa49236d20 +CT: 58dca29b5008f74bf132947df768dc85e2492a381429f151a3bad3132e63a4a977aa09f10879d206f43f27a26909495d0a2c8cb252fbcb3abd953f6e0ef0f6d5e89d89a1d9ecdb0e44686fbf5567a6fe7557a084a8a5ef5316890917bc432164266a331118c828fad4f5d1776645d163dc5444c2e12def608efb47adeb8f9928a5ffd3c46f963a749c310688e78525e34a510f529472a14bc7a5b65594338f6f5ea1d95bb5bddc6e8e1d1a449d126442accd162e4e03c10824fd48b32df763de5d7700dafc54206b +TAG: 141c80e1d044e1e9cf1c217bd881589c + +KEY: a54a347a7a388c2e0661d4ae1b5743d1c2f9116c0a7aa2d6c778a21e2bf691a9 +NONCE: bd3456b0dd0e971451627522 +IN: 3d17e3d9b5020d51295f7bd72e524027e763b94e045755af4b3cc4f86bce632a1286f71734e051dbcac95780b9817b5f1b272c419e6bc00d90c27496ac5ab8a65d63c2ea16eeeebe4b06457e66beeed20fc8d23a9b844ba2cc3eb3d87e16e1230fdb6a9134bad3e42eadccd49baed5e03e055f389a488d939c276982e4bc77f0a1c738fcdee222e2641b06fe12ed63ede2ab2fee3c54d7901d0911c32980b7c663a67d35ece23136c77f8e4536464225ab427d937e7a4260460d55bb5fdd7ea2f105604c4b0cf129dec49b81b1 +AD: c12d1ffb08acf27d51e63f5c0e311180b687438e825204074d4456d70b7c5ba9903ad0b0778a5fe36c3e12e82718c00f5d1ce585e5c73b23d6c5e41ac4a180c97c9418b07ccccbfc58c678e97882ea36395c0a05572b4cd25ddb3c32fa580c89c48a0e3066b8032e3823893a5721a4fd1e59c7d012a01b9e9afc12f3bea93e9d1a2cf5cab26e064576b36bb65606de62fe2887ace0cf399dec08da618954ce55362c8a2bcf31457a1804bbfff68a76d752f9aea81be8868bbca8f1af3375f7137941a1924b8a2b178f06a9e33f +CT: 938f8f596e17eae6920410f602c805ad9715833087e1d543eb20b1b313771266dc6a8f86f2ba033609fadec92ac38c1f1f0f728e568fe8bcecbae2ade7b9c4128fb3133c8b4107ad5c29cacbd5937f66905e18cc52d9239c14e4c8edbb2db89b26f5f4a9ff0f2045192fd212af6c65e448834580deb8787b612d6345466483dbec00b03fee4751f543a6155f2dbb745c1094e9721aea3e544a894e4a19a14645725cb8fdc21d259e086b1e411fb1bdb11293d0224ada25da2896dfe0d35095230af6894404d27d901540b0ec35 +TAG: c55c870a5eac5c0c774dd10dbadd3fec + +KEY: b262f6a609c4ad6da3710d58530b634fd7bed875956d426bf4b2412209902233 +NONCE: 0b455031d28e4e17a45b7a60 +IN: 9cff6ec8832bd0e62d9063e43821db6a1e0f3ae7947ab4d029643b0e7db8224f8bd00a2c011b246a4d5eccf9801fb314aeadc0532fa71cffe188e801d7c045e81b9dfc5cf6ae1e310b363adec4e7ca52fa754ece2540545a5161eaf9ed5748070b6e232125fa8e0fb7548fd3eed57a6be72ce0a9112f166776816a0a4ccf8151b6b93780875d03ea3d59ac57e7904c83b90b7666de85f055b25f9e342af4cb04b0c3f123ea0906c04f252f2b16b28d612e37b2a7b788d66beb8b361385efb73a825ccfb1a5ca55d60afde0349e5dad8096c7 +AD: fb99bc661b51464c0df92ba4f64c4c56d601622287bb1bf8e0a082ed3793e74db6a2f5a546391ef55dc45fd2f24878834bdc2903054d9d02ac05bd5ff122b65555d7ab1664cc36b630039e4432315445f303837e57149fdf6bf8d6856ba97abc5a18b6cd2f8f28cd3ac079355b314561c50126812861c39180fd94f9aa24edbec37bead760093d32b96ce30e389f63b2b271fc051b42952b3f5cf3950def581f7cbb2b4aa5b151a16ed3773166761232c106d3ff57851895640ea12befd69daadecc4122b4a481e85088edb093e02d5d3d8a +CT: 5341e8c7e67303d5374e3f5693c28dd9f9a5c9368efaaf82d900b4a4ab44337f7d53364544bbd822020d79443e2ab0fd2381bc73750203caa3d28858a8f9a6dba57a7c5248361ebb152a81a89c00b1bf49de9e2d08c0243b38eefe316ef89164b4907515f340468291e0b51009c9d80cf5a998d9cd8fce41d0c7405fc2d1854aae873f0e24cfad253ee07d9f4cd27080ee8ec85d787459080a06d290e6e721d23738470835f173ed815f1a15f293ffe95ad973210486372e19a9cc737c73928572cbc03f64201d1b6fd23ebb7b49d12f2eef +TAG: 5e0ac1993ceccc89d44cfa37bb319d1c + +KEY: 9b4387e01c03d2e039a44ca2991aa8557dea6179d19259d819d70ab2d5179eb0 +NONCE: 852124b4e04d7d1d63743d74 +IN: 92c6f01cd2cd959495bd8aca704f948060bee01ca61c46005b4db43e2e7655af4c0d96656cd75d904325ecc325f5fc9a5fff3eeafde6f81323b0e3b64269028cb64c9fbe866b400e76487f1759d6ab8fc66589e23df0c008974e1613bb4ec556bd1a6a0751f6dbbbaeff219874c57dffca59a955e0aae62e8fd6a904a50fa7eaacccc6dfd4a2b8c6c040505d3448ed2217b7024224bbc4335c63b2ae8172d7d3088b819edbaa17991a4729bcd5a456cad20ba20dbee99ae56f8ef669dff93c99a995c8f5dcb5d113db4178a49516206a1cba7d872682b1 +AD: 92a1d2574182f850e37aa62338b19f403fe99dbc7ddbe1e6524ac67c4092cfe296b5ee9b94eddb5c228c902c18ec1ec26e1ef0263d05c5caf1c71ed9e5ff987e9964b46f27be05a83e20867f1f2107db26b6bc7066af2b0efdcad2b65f2ebe8b31fbe2f3c30171f2e4969f1650c9642ae47c8db5bda47e57e8a9af210a6fd4894dcc2934b4ecf823cc841cdb3c93ecc779b455b8cc796d7d60437da201c3f848dcd5f45e88973e06364e7cd01afd2d49fd3032550f1c1a60c4ba48137398f4d58e5fd0093c06042b103ce0064f2cd1cfdd39b7440121d7 +CT: 28b87d324854d5c9c6ebb303fb802b12d946ed681ed5b3384dce2cd782bfbd022f213f193bcac579176440bbf2af378b019d21dde5d70e42d257722d15417a9fecc8e56430551ea3bee798a01faf74d0fb09be6dd0c14cd03feaae29c7d17581e1fda0b4bce632ef790202e98c8c4f8f842fb3e33b3fa5e8700c8644ed6d64280652bc2a5d40b3ee0e47dd5a9f3535e15b1fabb30264515afd4f9b1caa5c224574636935baebf6d1992bf1a7a3d698d457db4248a2b38a803837ac4fab7998722d52de61bfab4f98e1933a77046bfb3941bb7988acebce +TAG: 1b07d58be48b81f7007e5683b399dc28 + +KEY: 9d36155d429b90b5ff22ded128c9f0cfe77ed514d410998091bfca4dce7e3c88 +NONCE: a7b73ba1b2b0e846c3f635aa +IN: 2510210b420b12300d51ee4a7ad233c9c97d71672c0f9a7b9041d32172fdf3a6ce274aca77a0db6961d7921d1681ede2c1088a7618382481296778e7f56d2c0074c7c545ccda313495ae2a6dfd042474b07d2b59c79a0cd8c3dc16132beff1687111a48ee3d291ac556987e73c5a3807923c2deb3b9a59a135a8fa0d85d5b39016edfe0649dc13be672a639db58839d3362eaeca046767fa1182ef8a63abc104e7cdc8610b1e956aac89af76b40844a358fe6f7343d217e1838aad19587ab4b1c765d2cd7bf7018e338c0207d4c9dabdb1625af0c75749e9a20a0d8d +AD: 39e96c8d824bee306189a3bc8a8d4862df55e8016726222a528d76de169746a363e82e82e359b774d061a6e98e3c35aca8ba802a5956a2c512501fed44ae341cfa65ec9d95485763d99cbd9aea078ce551f7f82272bf54dfb6420ae7653f275ef145b2c87720c9ccfa56bd286c61cb822d0473dc2cc3fa22d50fd16bc0358e7c615aa1791b990f30b1d737f798219f4446d173e80fa62380dfdfebdb36b1284a62c2b6638f28fc370034812d09b57d27e5b7d589075bbab42fcd6a91fa2714538be6286e4c7b2657b80f045df7f8954738efa7d49a38e5a55a2af934 +CT: 8cb991b10218bfefa522e2f808dc973620ea391623947cb260b852efd28939ccca4c8b1f02d66fd6d0d7058854fac028fa0f23e8de801ed9a4361bf7e5a23e6a7086624a64a29815bedd5e5ebe4d9f9386d47e1408286971654b38ff8e5dd1fef7686d7614ef01900ad33bf97896b4ad02e7445782b1794b45af967ca3ba72a2e5cd5252a9ff0ff550ee56fdd8aa555bbb0bf8a5dd534fd65b13235fa6650761dfe2a28b2757077a2680ef88c84eaada743d1f0d25de38fdd1974ffc07dbb9c7fa67cacca309a10753c6e2561c4784470f5c7e116e12070fb3d87131 +TAG: 665fe87506f8df07d173fedcc401d18b + +KEY: bd187500219308edd6ac7340d72813ee20054d6d4b1bc2ebcde466046e96a255 +NONCE: aab93d3181e7a04cedf17031 +IN: 55b824816e045702526f8b5def71a0d023a2e42257fc1e06f9a8531ef9f7717474ba4f469e442b471d5da6e71aa635a307205c0a935a54b8a59be8856144dec435e29aa1a3568073aa6bd3439bc0f219fa1179ba0a316f7d966ea379da16be4db2f1fdac2fa6d00bef9351b78bb2773bc30ddc9d019e6e7d78dfaf38010080027afac33e751c0429ef6c70a1f2d01f103482818e9353e39a3a4b785a7dd2c7e1ba7a4c36a5f3836d5465c002bcd1ac576d90ad276952ac155dabba6873e6d92b5278280a540071b205ba99b77b7568862e70e6ddbd804906c33fa130f8b0862001 +AD: 11b35743bbcd0113d2c188f75d382df44e874a2d4b3c3148ecf8e0406479305f29197a3a71dc7bcd71b6136ab11a7cf46de80140e15046acfa18774cbcc755e9f3beb37202fc308c03b1c20470b3128f5b91d925bd6703dfb3277d65159688f656d5ccd83d2beadfd778854472b1cb8fe440bdb7efe806f4cb95249cddf69fa0013dc5a626eb8ab69a48b3ddb1a317b35f7772f711221cee1cee9469e2639c44448c5942c95324dc2fcfdc952e05aa336ddbaf57cec2d1b33981ecb8f70ccd34a279b211c50a7784906f2981a2d2ad8fb130100c4f6bdb09c95dfcf4b0eb7ac6d5 +CT: 1e99d06f82333ec8e4fa1e81014458c81325e5d69db561449b153727da35c0b540c570b60488aca6aae58f75f84792388d0160dc45e4e5bef552c49228d806fcc22259f0f94da2f786cc94a3ecf3cc15ac67719379d86abaa54ce41e868110ed2b56dbeeaad4a444eab51a96aed404a4f4b9677d22345fdb67ed0df091d23d8acd70bf6cd29f19c99910888b3281b65637590af984e493ac70011486ca88e72fd14ef1cba06a50070f138dfaed35ab12690a14b1c8ac319f597bb690cae28019d64c868acf9a58fde1d8aa18dc1ec9c3c4a0ee9c4cfff8912b1bf23c805af6df48 +TAG: 1a43147e6e097a46b61f8b05c7dbbe1b + +KEY: ce53e967bb4675a51652a9e6e87da6be36d16245c1e37ee00bae09cc30ed8528 +NONCE: 0f53ed18bfdd28918c3993d9 +IN: 3f2416477ff2ce7da3e5766f043e7a06ea2b87fdf06320d296c71cbaec4b115da356f8c7f34220f91e90c97a5cbbb7fcf0048fb89414eddeb2ec1062d08cc75a39a1f9f214fc3efd6fc8e70d78418007d7d28944b3f37fa5667ff79098d7af36a9324419b53efa76e98a311e1436ecedd977397cd02cc8d377ea8558edca35ff4c71ec31943119b76af4c78a435033eafe73c7079224bf2328b49ed58acef9b043ae3c7ff17a66b521e190d6ca2b2835ed8edc2c173f04616af237391a4440fc5306366c834f6a504e902dca6d3e9e1554088eaf5b15db7fc1fa19f0867ece90ded639ee8072 +AD: 64a596ffca0889833fcb537f58d94791f9ba9b6b7ce0c7f144f2f1a95d62ce334f7bf7f0d2ef0c6e7afa2324b069dc6a7a522f19a001c335cc0252ac4a26079c3f267cdca1e3f933069f52fe72e1a00c83d8fcbd2e76149a912c7b37663c2e7967a3a80656c87094d349af6b9d64b3873f467ed376eaa1e0abae06180c847e981c6a12d32b580acd34f779c343f8b79df1b5004d333a5c37a8be7a94c6f6400f819ffbe6d54d3c1a92824fb15c279fc8121c735b6c42248ee22e665245966d40eadc51f12904cd64110d69354cc9d9fc415b3469317d5e4643942dd4b649de0ee2fc5d200701 +CT: be462da8cc9d8cdf343f7025df0b8b41c24f7b6060cea2d3c63338b6c3e83f0797e966b8c5dd889bf1b5058fb4d694be2178fb33d9be1a351812046a6d3bd36c84ee3665d39fb98159e4d30f8a25a60064caf980f744fc519e2dc451f5fbcc0834b72920d32f0492abedc1022b0db4f2f44b91ec48c588334775fac91f174a4714b3825e96fa53cad3de94807f3b888950c8776189cc18fdf379cdc9d6054952c6ed2b3fb7f6b49beebacee7ddcb19a3eaee2b2e2b7a5d6476e5fc1f216ca443b859a9a661dcf2f7709f87361186368a62f255d78150f09ad4ab1a20e7329f3d96fa2a33cbf6 +TAG: 1cf74908f6fbfa5b2b309ebeff2f3ad1 + +KEY: 093d932ed969cfae63f07e0c04c7f9eaf1b36f656095f8d5f112517dfc430cdc +NONCE: ce36a837ae93a280d2fffc63 +IN: d9da99635f8d728843dd587cbb24e68e1df2f81b5f7abfe233a224cdbd48cd8b82da3711d2ab6c1ca722610b87f426a2cdee4456b50781e3b25da037ca636f2a5eea01f4eeea52d0feb7f1f6c2594d63d8c05c2adf339839449cb1d2aca94852d1b64b5641a572c2da02ebe299c7d1ff4da8706f44b14602f44c0ced711fc78005f87b1686106250d3d3860b67f5b38788db1891150f88d4c5276751afa0b2e37a59587cd8b718767455e65eef25bddaf787d52b88556710f740f117b02f244edd47cf0e45646d40e789671ae61ab06336e24fad8b64cd8f60b427ea1f58af443c6f55d54028edd5f40d78 +AD: 5e9c95c3449cee3f9f726be031089b2358ee92fe7b408b355739c8da6369304f3b287ca60dde4685bdc59879e1530ffd8f6589449196abf0f0dc6dcd82ba7fba481f13376cf29b32af2ecca24a161e6e57b6db70a7e02ee2154cc0bb5280b08f8dca35b1a342fa18b8025c7a805cebaed99e30b43c139de7c37adc25b0b6b5d873ed86530622ef2d0ed3ab19e9c27df98a4a15324f902c35a23adcad4598c6e990c64893355be15fa7320c1935b4ad3c069c068d6b3c8f43d6fe0588b59170bf567ac3a53a50db68e4be17964f55acfe695638cb5fdea5c40805334a385c2d35aa836637ccdf71390487d9 +CT: 40380718f069f44c88932af22a10f80513821caa71fd7a9e5c4f37e1c756c43fe491ac13f244bd1299844cc78d7812110f570b693e63614e639ec7395cf65c206eb6fc9bba86f89d03dd19e45d5ec64c7d3a308ced4ac1f59cf4e13be64e49acd9ebee209afc508c97ac817f1367629af9d59b0cd48f138d23abb61f92dac530351f46a4e7f70ac87388e44f6e9548d3e6a26884bb7611f632da7db2a12fd9174773e685df316ea9401d8b352135b6b32a374eef8661b77eeedc34fa4178d0a5731ac9bfc14bce1dfe96af095b0088371ab1a04b2062625f0c4fdf01fc0a6bbf1661cca11932e93690501a +TAG: ef7f960b146747ba4f25c705d942f8c7 + +KEY: 86875efa72ec1827f133a8935193292463ecef801bf3b461c96b0312cfcf32e1 +NONCE: 738136465c8935d77c8d4ea4 +IN: d692d3ef47a5c9d0d9a3b6a0d498e90a3ea06278134ce90cc1d69da2159d9a1f5d0a9ef4b4ce5f873e26e8f9d53ced79991491325ba5511be4d9e6563b70459b10e60d8c5da45d3b0b34dad86772b0560314f0215bef7b55c6ae53999cb2d6a14a35b50fe5a1598adb7ebeee097968ee7624bde42862824900c8cb45b12785d9c4d50ef38133d31a66a612d8638008d03edd19c4d7edb5f9b9f195c60883a7d6aa85bc3ca3b59c395b85dbe9bb30ef6896c4ebae8d72cbecfadfa451bf36631aefddd3feb36978aa8d9a45c9fa09bfa0b2c040d9a422840e68f4dcc3eb902f6be1d91b11e1749183d89715761b6cf22c +AD: 17208cfe5a96adf0ec903c7618d994492d3eb77275fe5bfce5ab1f67d27431c7746314e52934b8c44481e5760cc8f6b0e17d1fcac7fd5b476196e3152c3dc90adeb58c2c9c62cd684b4b18d4a94f8e5b4336ed3f1758b58a254f48b3aecd9cfa63cf758f2df54c52eb246d046198b6eabc90b2a0dd6c5323e915a117235174fc9089cc9bcb1a3bb49080cbcc24367e7f4e17e27a2054bdda0ad8996df1cfc6bcf43f70cd854f4d97aaa4badb5826dd86765d36a2ecc83d3daaf31594eff02999a423185356d693f26025a576037336c156543353423dd3b5da75f45e297c60dd8e091b961f60eb6786fc988f6324f9e8 +CT: 55f48dc2b6836b8603e19264382ddfc568b1bf06e678de255d355fd865ef03339f644312c4372494386589431d4ae7af2eaee5dd3c16340ecae3e87dda9220a5f9b9fe6cc3eaa226d9608385b7e8a6216e7da71997088eaf7c67b5402be01c0b182383ed3c0e72e91fc51fc99c59cc8271660dd7a59ee0e7d9626ccd4439bb9a1499c71492807f8126891ce09451d07d9c5525c5f185559ec44aa31498be3fc574389cf948640dcc37d0b122249060bb7d5d7e5194d4b7a7bb64d98d82a1155e30970a854f7c0d294fbb1a9e058f3b9f4762972c21086e0bf228768d0d879a9cdb110f9e3a172feca7417d48b3fa0b0b +TAG: e588a9849c6b7556b2f9068d5f9ead57 + +KEY: e9467b3a75dde39b0dd44e7cbf2b70ba1757ba6a2f70cc233d5258e321d5b3ad +NONCE: a9756c7b8e2e2f4e0459f1bb +IN: d6d7f6112947be12e7ec8d27ce02924503f548456d0ba407bf23e848b9ecc310e4a0c7b00c0de141777a94cb4b84a5cc34b2b05c8a37cda08b6c2dba80e80853f2a18bcc41341a719f84262b601610a93721f638a8ca651a2f6c03c3cf1070f32b92c4ab7a4982a8f5e8ae70800f7513405f3ae28ba97a9ce8241608eeb5351e6cef5560c4209790ee528b3876896846e013a0bd3a1aa89edaefe08fb4b73b3fa64c0c8b0f7ab70653ee138456319230174f0f1f7f3477f0cfc80eab8a96e29e85e20658cebb830ba216b1d8281ce499f729278dcfeb59cde3a043ef3fe2c42705f311a422e9f80fc3b58ca849dd4b99e5e66a958c +AD: ccab7afe4d320e94f77963d779ade1343e66ae80446eaa5f9ec4d3e3bb3166255e4aac5707ab407b284dfcdbb18ff515cf08790f0470cf335946040438c7de2d2a342096d7607e1920d86b519e96cec1715f4b0dfe375c5959644bd664d23d879b825dffbbdc458ea9da5ede5682ce1ad1cff33dd8820761b1c067cec638873a3cae79c7682ee8d4f97cb96a413dbbded1c242ca669d50ebb6de3c27eca3041fa8aee8974c3d17b0cf79c32c7bbfe20dcfd57303cc40334fbdc43e925df1d63fde57bf60553d7790fc56bd95e675db934dabb1125eb97cded95f397b32bfb3a2d40703e3f11c6c226633b3cb7f9da1e3367de2ba4d +CT: 47bb258ddc0945079a0b99ed5cdc0186f453f8e0393cfea258412e423dde4a00c014ac298c4dfe7c03b0d9bbd4ad189624cb6fbaf13e60ec2b4d83c5bc3294dfec30bd6c8f7125e11d7be145a966dfd78fd77af68099b855989fe077cd9f427d4381b4930abc1daae55722540e4bcbe1b560fde208ef1c2dfcaa2c51b76072e67da311c2556eaa2c25413bfc43d00dd84aa8859b296e05945683e028699d60a29227de1363c4138b9ec2db8f3b502fe09d368c5f2ffd81abe50cc1ec1ef216f27f401456d061429d1910623af00bcf500cbc6509c5aebf7de9c956e40a3f0b0d562775b03c282c204e33c0b380ce1475eb5c0441f6 +TAG: 9ea19333f5050354a7937fed68e38dd4 + +KEY: 4e323dedb68bb5cc4cf2edfe3a54a19b410f849492ed6f66fc053d8903c3d766 +NONCE: f77b876eff796db621eabe88 +IN: a7514c4111d7d8bce2d56faee25d9f5fbb527162576b444fadebf42d48d2631cfed344b0437ce8a7609bf30bf0a44aef172f8b12ea7567cfa5dccbd08bb3115efec59437ff02e7128df9d9e5193794373e30dff7b3d8ec0fcd6cd3872d755c0314f1cd9cb996e4c6ca8ee2e35f9b64a1f0bd1669369f9b333a356ba58e553ff9bf9cb6c5522599dccca2f7f57a91006e7dca4095d11955e5aabff69febb98a408aee92293c0abc12ff23482ebe9d541bf8fc7493eef2c68044dd185eb243b54a2bad9844d831d9b0766a0ef013ad3ac03627b1feeb287e5e61875bb1d0a01315761bae6323a9d678cdcd3c4a85be71b70213d081b348c63fc603 +AD: 9bd10dc97ab5e9b35e1c8c36ef37f90a11bae7dd18af436fa8b283eafe04a5bbb16bede6ce1260187299ae6474628e706cc08b3627f5243f1a9ab469455666e6d5f2ab597b6799bd60a365a9248341decc36d473fa52ac5ac469b965cb2023d43b437dded84ad49de95a6dfc6ae4bbefaf86f9b06e3a33ec90d32ea3af541fd2c43387c75dbd94d44b9582e8ea41afba5e49f1d158d48e979d04888fbd42876e12bfd6695cb99640c537f2f9223d37cf6b627207b9318bd1f4c64556b5db1101c486c53dd8dccd7405e148d6d9b38b7ac875a44bd6df75edfa4da8594a9c43b223e7a6f5b81a5cb8dd6e06e9a976ef156e45520af332e4d56035 +CT: 9885d7a11004ec546955fb7a8c77ae57588fa2e7fedcc8e9000123495b9016d1a101fec1e6724302e93eb8e01bd05efbe8502eb97b1064bafa9bba5658b1677819cec4998dbf02df1f1eef51bb3e75c19f570efdda98b0b8dc5dd9250eae8396090ca9ebecdb90f32c5e2085e86b64e57464d251af62d9f8c01d7bd6cec5f9dfa5eb7c4cd412077571bd071a4eff5098883940d63b917c08bf373916cccd7a446abff0aa5c687518703c25cd8d3c5d724f348e20be54f77fd18dbf6344d1d25c788ccb5a5747d575435829b1825e31f9e94abc33c0d2750fb62ae167a7a74fc9e39db620d43e0b8514d5f70a647e53dd5764254b7785b1519474 +TAG: 936072d637b12b0b6a4141050f4024ce + +KEY: e57e74595d230e8eae078df1dbc071c66a979a912e2252257e28447e97fc82a7 +NONCE: b613d6d5fff507e917674f2f +IN: f1ecbb2a45f04ca844616528b10ffa4d2c5d522ed4ae3366888fb371b6ee7eb4be53c8204783e43265931f58f308623f7b2733384c173540aa0bdf879fad0283c2be6c42a7b4feb2b29265fffdb518ea77d33507dbbff7d9921bd97fd27f1100402e02135f7df4b5df85f7472fa75618facca3e24d487453e831efa91242e62ee9d32880bc20f7ec016eb12edb589dc8a669f7c78375f915d7c2b03457b00ac2aceaf37c0369a85c3f6fe7c0447c022d66bb5acaee62163837a36e882cfb8579ba9182d3153a25623f339758ede5a62f67b199fc8abe235fe4b607a6804fd4d15378c76e0c26c1edf1cd637b7ea59edc66cd5ef9b8cf79b95ff89c235ab195 +AD: bf4c0737e461c1d6fc45b87175fd7833625c98a03e089c4e3d47c6b21f4bf38cb4b7666322217eb8fa022afae473df56ba3502c88cf702276bf39c6fcccf01e629925a83816a5096e612458af6380dcb7f63cfc0eae99d63475616b18b44111a1927b05503c4ce46ca48321b0f8f247a54919fc844fbabd3a2481e83bed8a5ee8086d7559db00fd1d64f4892ee9363d59829ce1e10af66696c28e86297b43190800251f346bec1b577446120529d486266a271c71011528b24ff4caf2c30f9748a2b03c788dd583541368a643075a52127c48b3b6f0c6ef413e61479c9afdbeb4bda44340ff0d81c7bc0321d3de4080cf7e108dda3fd4e480e685b202c6bfc +CT: afb2aae2dce03cb0bd3467447ef6895a132cec06b9f7764ee24d90078660dc820b8384c01375e03c20a6c688a780d7d7fbe5837d477e8f3d7ab3ab865dacb0eedb5694d3276ea914a421b03b9d4e4f586227a3af7e8d5d579bd832450f038eaa7bac57aab996df55367ddf59b338e5d370e310124e8ef43c9fe54e5d23d60023aee266054ea66c9f32170ce97998b527073fd178ed4e1752cb9c515c0b32766b363c39c513c2e9ff6d1c24807afb43af3c5a317f1536087d8576fa3be3b007d3a77ab0422303cd0b142c4ad194e1bb86471b91861235dc336dfe9666f4f2c6a32a92b8fc52b99873f9792cb359476a2aea21996d21c17ab814de4a52eeeb33 +TAG: 05906cbf531931559cf2d86c383c145e + +KEY: 847eb274561fdf0c1af8b565a92da74641f17261a0ea4cf63ba5f36ba7028192 +NONCE: a379511688390ade6f0318bb +IN: 1e588cd0636f34b656b140b591a9adafb8dc68d0abb75531942e3c6ec1d29e4f67853e3d718dbe61b733490525c7f9ce6746f8639e4d271267a95f0940b3406c67ded0aaed36374b9a4bb8c753579051c6dc3244d6126a8a97d4a912569ba139d55dd00c380e7ec450d44f6c7b9482c2594b21f61ef8d165666c830867139262be5ad3a31f44a286d7e86d4e5c9bd6118147efc8e606c522ad0e9a218aea4daa39d1653157e4c3730240fff67a42e4f34186de1c13ddcb1e44020b7a31d21ba6ba96b3f42360dd1d754a7bae75b6fdb6eb3c76412cc1fd8e900d7aacf4d897f4224f19a1d44a77e06c95eda5fe76b11c6f5088e8ca75c87e07edc64c09a6a31371552449 +AD: 331d48e814f660516f3a796b08afb1312625b3b17218819cfdbbbca4c333378b57fd93482d971992b5b15b62f0724d6e7b9beb5ddffd3c70b6f8bdd3cd826663eeb91d37734a686c987efeb4d4906b80c5378fcd07806d2dbf3eb528472a110743df8cd96b6eb67e98b13ac506c9bda167f045a412c93d78e860c9b4bbd7a2d71adbd3530f30253847b4112d4b898b520c7a14fd075e62605b05084f26fd138179c2791fd6e8d3bfbb2735002ae12d986f92d7d300fd6f1dc12c993449f8522f6f32f506a677c8a981aef9815e83019713b2f9943acc8d5b3f6f65b9e2b9a14ad2e300d636166da2d35a6a0a756a76d08709a043d65341695490124971a7574cf0b5845a +CT: fc1f0d7309e6420b42d59740c9b9d4b97075b874015251ad55483068b00f87502b18182b140db07c70a80fd884fd79b7b5fef1d307ca4db0ff046494443e1cae83478d275c31402035f1fc24e26214b78d9a4dac78d074150012f9fee810a121d87a16d8e1eec5700e9facba350029788480a259d9f30df1c2b8df7691629314391719853c0b68614134f6028865700b1fc4e7f34ff28f449c6abc3027f38d7a7f6d84b8f27f7cc5afa09478c809eec346bb58244ab42a3bef61a14ae7640d76591343983de9fe5f1b985ce56c9fcfb2e3f6220779ca6f92a6b8aa726573b38ed7663ebe4c85066ae3f488ea3309593fa41dba8efd2b8f44b9fa8f7a427823c1228093a3 +TAG: f1832022e06228c36181856325d4eb68 + +KEY: 3828b138f72f8fe793d46c55ad413bab31a51e7a9093cdd10fddb4739e28e678 +NONCE: a60413c0ab529ccf3de58468 +IN: fec017c1c51da5ce9dcd8e84cdc03a43145b31edfd039c7c85d8811a2f58efe7a2d7590149a98cf0b5af82d3e0a325223bc9d5585ceb1afc4cdd96024be6c8064c2abac14f68e65de49e25e3e967500ce5b4504d00a9cbad1e86bbdcf65c01a7a92de27583b7b92122b6a4923b7192994a1edf00b75d14a982f92559dbc2d5e427a75ad29715375d90193ddbb39b9a52c1a23d75629c539e0a6ce822c7c08fc77dcd3adc357893215df4694673a16d34513de21217ce86897c8f0575d213ce0c66eb1d1985fe73dd86da3ab5e89df4243e1be9dd95af94f878995d02929ee42a062100d6d4d3884730f54593d5ff7b7ae53e03d4f0e10f6f4c3077206499ab7d4de1e825d532d0918f +AD: e2b16ff2b6c73c9374704ffb4cdfe7bad9eeee32157f2eedf427f99c2cce80c5aa4d9145e85af0cb08e6ed477cbe79ee168ded5c0895f9f4f939c21916b3dd5c9d268b3aabdefb85d953bce9b70732fc9acf6c7b727f78d8c9aaca9e022d7cf0f95583e81744227d87fa34ae19de44d202ba01e3d03993f38c9b2fb00b54dfb677d67e6f5a15f46c29eb5597ae3d5384b37bbeca3f3d825e2b7cceaaeb36a8c1273062259608956dd0c79877cc460d0268de27355e34b9d8d1188c062ac5e10a73f2d70fd0636304b3de06cffeedd246e2db19b8b66785f9f9c62b8f0198f29d37a4ab5280f4aa0320559810f89a1618844d0ad5f3a4f5a0e834ab31e56798b7158217f834d372c36f +CT: 88ea11ef6b6ee6fb0be77bcbf227e77508922550ef0d7534bf05668ae5fcab2f4defe643747716e7e000950e36c6cb24b79987389a150382c091d39ddf841b0a5e31d763d9c59753a3ef36a23b81f38e6e715357395ce715d30c14d6ab5b7454804ecf633daa39b6107f562fae6a646efb25c1119dd17955bb9e640105a21566345408f72f2acc8f2726a0be465551f9ae566da559fc0b92c36764c5ca20a18a316c02e606030a53450e7ae1146050a48a64c600d33cb84389b0bdac7ff45d3d1f2f669a6e365ef722d76d2fe9bef2df93c58bbdd6965e18111b5de0f4a62dbb874161bf8adfa61e9cdecd97b4fff668b3efeb3e32eeb929cf58d94ad8077c0a2ca79e80877c5d9329 +TAG: 9b47afc5816b7229213cd3c9135545ed + +KEY: 91ea63dc27d9d6bbc279ec6cecdce6c45ff0b247cfb8e26b6ab15f9b63b031a4 +NONCE: 80a134fac73eca30459d5964 +IN: a848e41c77ac8c733370435b5b6a9960af36031e96260d5703ce15b003606875a7901cd11e4571bf88dda29a627c0b98065a8b4e6d382852dfa4f47d86fa08e48ad8f5a98e55c305900b83200d44029f304abd21e0264115192a3fd7b0eb69b9f8ca7865b3be93f4ba5a28468fd7bbb584c32ae867f5146efbeb1412d3ac36c30cb308c327a6f207e30f561d6efe0a535446c693e14176e9e714ffb5a5b1075812909a362a6c4bbe18322e15690c2c9cf5a18e0120c11551cb7055b5aee97e7a56d7c24fdf1214641c8eacb196d74f3d96a7fbecdd4fe52dc7b6ead9041cafd5a3fdf91fd3614e63189b488d4d7c1ea3c6351d112a2223b29d390ac3ab7f09a60bbd3df6e0d606d902aa44244334 +AD: 47940a0694183b2fcb5e760c9ef6dbe4cbff6ccf33208337a981138f9d35c03f8adbd810e94636acaebef6791b531a65e99b03fc78e7eb48036615874e97cf762fa6ca5d880bb2c2f644f1aed70c667880f98834d501caa277cb8ef1095ff882e79c3a92ea8982abebf63ea9ed7e9a24d32cb81d5d98e891974e3d636a59e165984e00f05a040d33f07b39eccb924fb24780a422a6b2b7bddb5b316beddcf6fad20e4cee7d0141c2f7c4e4f759db8691dc7b8525ccbc3ee6071a2ead63e750d6d92dde7eb1303d5b1194702b6c3e0c2e6f9649e60eeddec9c1f71cf309af0672cd2ffcf94ba7e6c3d7cee020a224a9a956274d1d36ba16030e215d90a165756666eff066a8e51bf7d4babe8b7d8d +CT: b90449af99327afb1124bb24f1c8b5cb878423b0370d5f7cd297b28cc4135ee77d6f1913a221cfeee119bafa873072bfa79e303fe377bbed05add41ce3a42ca4632b98f40a36227de1a9ba84d6176c01eca9d33d954d0ebdf4e40f136e0f6a56156fbb33b344a8a433941fd6e08774bd00075aedb0e396c2bc37d1250541248dbeb899e1b5170cdfeaf7b89995b049428bb277c501354f8cd48fb58f6f04f956dfd099c48778dbdbb4c95b7c9d6797cf6d3bcd1d00e88cea885ee4a10d94356509e148990a0e10dd89103a9d5c8434a7bdbed6c0ac1271e0709eba144abf3cf075c020e9f7835d5a98fb2439b399e377ae6e19fc5f32df9ddfb9e936190d3e9c62de99835249d1f32ca3f92ecd44 +TAG: 6ccaf7c142d86b83e4d0b4289b49c4d4 + +KEY: 1344db082889367fd48c5f06bc39f9cb9e3ad4b92fa484ccf49418dd4caa2e19 +NONCE: c04a98e7e29326b5330818d4 +IN: b0e12e3122c1ebfdcadded5a45163a6208548e9bdf95cfd18ea504e5d2e97372e58dbfe460a57b724d38f3bc0ce02a54015779bcf127343474d7d4c1402d598bee56897203b903da5b819e2218bd0d1a2af11c542544f02c46969cd2bfac683b76a8de61698ccba63361a1a0b570adf69d24e9a7e466873c8c12e25e0bcead7828386179a4d65d5bbdb800eb52fc01b67498d7b5f9864270162158a8572eccf541b07833f001848672098c57708eb479855799567c318b1aa097efa70db0d8a8d36fe0ac22ebcc2870baacac690a79e07ab286acad9f7a877939cf2989cd6200eb86dfa7a41e969a3683ceacc7c97d1cd5487f13c439a9777a67770687657d38267a347a0b6d3aa3cf64e7f31017246e4369da +AD: c96db14dbc2aa0ce3ac63794f75c7e78037dac6763282edb307821a7938de4baa3d2e35a8cfe0c8724c2a8d870d0a462ea157e15aacc69a3c881d9c819225ea8be479872d55e655c897936c95b9ab340820264567495fc5e4e3354f42b84e191b470ca9f4d8fc25d011bf9c9e73e1590e1bb919dd2f288b26935fbfb8c93e54331dc8edad5e1cc4aec103c2f3320d59870c1770319f105ee790b704ed655be423e63ab040f1153f41e7070ae3a0f34d217c4649c180c84814463902d99a9396f8c7c85a3a4c8ae2f01737649fae478a40fc72303a108822775e9c421f945cc0eea992730790a9aa0c0d014518dab371b52d30b5a560f34946a9344cfb8a19b09ee9b123bcb8f642780697508f04983b790dd2d +CT: ffda075dbde7b874995230e1324f17894689baaa7f1354e26100befb546ea23dc74807818e43a3cee00ec1bbb95c82180489ae5f3a1c482dec28f96ecaf5ca4655ff7f33c814197cb1973cf02a0b720a5c44068d8ddff0789fc1e7f20ef408c1a438133fce4f7a3e8c85d95a381b94e949ce47a85895c4be7cbfad468e52a160dee34b8ddeef2ab280eaaed4990ecec790ac16de3c74aac6fe2d5e28ea2b66a921c894a3971cee4a2158054c3567e0d941f867ded5ed1d21d8ab090848fb3eddfb1559bf11815db52b8eed871cfc117980f297da79da31da32de3f162a03d95090d3329da3662df29e6ec9b236e0f7c1d7d957cfd54d5efc99c694b9dece989912388254798513d881e5943ce830729a8e2ddf +TAG: 81c55fe9aa2de0d63efe3f74a3d8096f + +KEY: 31dbefe589b661af00a6fbad426e013f30f448c763f957bbcbaf9c09764f4a95 +NONCE: 147fe99bba0f606c57242314 +IN: 908bd801b70d85085dd480e1207a4a4b7ef179dac495a9befb16afe5adf7cb6f6d734882e6e96f587d38bfc080341dc8d5428a5fe3498b9d5faa497f60646bcb1155d2342f6b26381795daeb261d4ab1415f35c6c8ac9c8e90ea34823122df25c6ddae365cc66d92fc2fe2941f60895e00233b2e5968b01e2811c8c6f7a0a229f1c301a72715bd5c35234c1be81ef7d5cc2779e146314d3783a7aa72d87a8f107654b93cb66e3648c26fc9e4a2f0378fa178c586d096092f6a80e2e03708da72d6e4d7316c2384a522459a4ad369c82d192f6f695b0d90fcc47c6f86b8bbc6f2f4ea303aa64f5ce8b8710da62482147bcc29c8238116549256a7a011fd9c78bbb8c40e278740dc156c2cc99c3591fec2918cdeb5240fb428 +AD: 5a32d7044f003b2ffefffe5896933f4d8d64909fa03e321a1bdf063099b9f89752d72e877291d8da12340c5dd570d7d42984ffab5177824fc5483b4faf488504e6822e371dca9af541c6a97312b9cbf341b4198b0902cd2985ac10a8b5b5fe9691bb29a88344f863c980e4e871a72a8b74f92eef68c176e9d2ef037898ff567298e186af52ec62eb7429a8004ac46b945678b82859396d36d388ec3d67653aec35cf1da2684bbc6c78a5f9e3ce1b355af3b207f64e0fa73501c5d48a14638d0906c87eaa876debcf1a532c1475d80ed3d4b96458d2236eb9f67988863bc6d5c16b96b93d898683d248d7bc601b5035fc365481b89465e37a8f7dd64635e19a0282639cecde72c6b1638e0aa6e56f9c00d031cdadc59ce37e +CT: aeab9db30a579ca54195e54a9e6c787f40100c6d12ceee35643f36ae45f618cc9bb66aa4c0fae0ec2686cb4101a5b23a46877460c7e020b38b0d8d1f533ecfa99df03d346bc854a578276d7d5685ad1fb03655683a64aae4159c9efa6781f053057e0811226c7c533967a94587f4025353b28cc3a2ce5763783b4c31e7818b8ad9195bc03be8f294f9f6ceac578f9d30b22b1f5a68d647d46cf6db4a9c3a8a5c06fa97c9efb4578f501ea96db1f40942e3f24c44a7e4070a6b931c39947d9692930b67767357015de51a39e46fff94b6019e4bc1ad9d216a571ba0dc88859c49d2c487ca657384e49b4d382d86a60c8d5195320909c4e82fc077a3b22bd4eccf0f067e66ec78eed642b2d16f0f304f60f1d9ba69e205c982 +TAG: 17ca09e3084504fc22e914ee28312c8e + +KEY: 0ecc44c9036961fba57c841ace4ca3c547c51d9f126567bf41626765cfcbd53b +NONCE: aa98b6ddff7e4b2041f29d70 +IN: e49a2a5713f507bfa00c140dfbefc0c43e37bcb932e0741db03f0055da61cd837b6e2d8f99115d70750fb23685a17121b52e98a37c87204e0207729fd9219d11a48e57970d790338793cf329f7b239512a44dd4409fe9d157f92123dfc5cba24af106442644dedda87e1d9e95fd395f2f0ad8f7d27f313e6ce1a07d9845dec5ad732e6e4749b3a161527c8ce42331f5de1d700650072fb68e9c7645a0e0e529d0563d2727e3fb38ed341f74ef1ad95a0216a440e1384d0e7ef71cde38cecdc9e2b2d563f19014c40c1f92ea0af3b4f6da9146d433ae85f647153db326a28ef6ea2e0ebac0cc1aff157067c7dba7cc4317d56920ee9deab5764368e7e5b3ce8bebd0fa129f869b15897c09659c53188bf8efb7b6ac7d265c9b85fe96166 +AD: df41db4ef5350d4afcaa88b4a577b3370b96699bbd73e59aeebca6ea856cf22694a9399ae7f97a3bec226d82f5598f8949dfb92530dcfe77770f066f2af988fba5543b8ba7655bc43f8dca032981a34a1beff695c6908169d475c55b2119fe5578623f68a9dd85b653656881b0db4006d3336fdfc784d1805e48ff478fdc196601f044c9d33fca3ddde2db0102f90fff0b370f520e00e3786c2a9b0b4a9a7ea6f9d866f77d870c8ef0f3a8bedef17949a32598512af665679dfbe71e1c3efc3dee8f5d4499e20dc63281191751f67e51f201973a6675896484527d66bed94d6aaceff65fbc4192cec19452b8873f22d72bf2f4981fe656285cb24be5c58e77dafd3e096166b230f18d3f4197fe16f6ec84c060ce0793ae6848311a18b7 +CT: b15b2bc4b9e8ecc5d9c4a6359a805b7590bdb4bfaa9b3fc4d7676d721edc4b3b1ef71b18a3d78f1b31a477cf25e55b278eb3ed774805ae8e5a2a0204f7291d9587663c4d8b1b744154f3b7cef796e0b91590161f3bde82f1d8139cb8d017606ae6d0552ba144788fd8caf435ab09a43a1f4057776af49bad98fc35cefefb159cfebfed76f2e4d18b7be143677ff8b3d6e2b440fe68475b5a1193bcd19ab157d0d2257f33de8e50091ea3388648c3410aa68c830566a0413d92454e4eff433c3edc74e8f7516ec17b2c01cf57a2d7c48db97b706b8d7da0b68051f2d6a87c417f46cf217a48611980890f669d39b478c35d834ed2c79299df2381a1215d6db303cb63e2795fe517649874226e0a6dbfe2c86370b9fbdd8c5de349bfa25f +TAG: 7082c7ef72c82d23e0ba524132acd208 + +KEY: c05dc14b5def43f2e8f86c3008ef44e4dc6513768812e9218b2b216818c4cec6 +NONCE: 5cfe0dca6e599ed9aa89ba97 +IN: 8a06e2997b8e5f8040b22e07978c83c48d0f90bd2b2f8b426b43feea0b614d3b0681745ea4224cabcaa25ca45c3053a6300c47ffa4f72e838db135ae35c27939aad4cf7f75fb61daa3148d869057598e4e8b44c6fb19b0d9281e18676d8bc137489bb77a51a3a8f807a896d558f00040e8729ea9bbdc7db6102c8b99c8a1eacb0735577bc6533cd1d8147013935b6344116090a1bdef1f2e38a877a50c8fc0f394bafede31375c57476ba06d95ae734e6dae771a32e5091dff71d845c5f7385b9b9069ced12fcfea34a510880b088bb0016e94a5932c89baee038cbafbf06b3d09426afd2d5dd5e392636362e9ffa9186b5c753eb84f82f68fb1286ed06c58a5a936cad018ebc4269037b49f2ea0349373adea99f06062e5dbb0bf94f2883f5c0556 +AD: f2a3f7af8ea984bbd85953f14202c6e478f98d0bcaacd414329ec480d0c29fb4c1a052d3228c883928448f0bef12cee5b69829b4a3eb4680084131867cfc3d3af84fcc0d80c2292d3fe02405634f6cfb20b0fb90345da3a557fb30582175c32e432be66ad096f9425ff4060df54d6741fd6567a1e2fc5f6f3ed95cefc806ff64ae91ae82920b5c829ea026f83fd90d760e240da3c9ddaafe4d08507f4af1049056dc6d09657779a3dbd889d851e97d4ac60dc66df2d24979ba8947a7890a304bb301d0d42b67824e0c68fc882e90cb6deee50c2e3d9f0da59ab23c997b05635a0d56c71fc39aa0e6b19c43a7fe12d4e4145453cd7fbd8a3f33bf5451addf05052df7ef044a33513bc5f1a4cfc8b68015664bb5c8e4bf54a85efff109ee96af75d4a5 +CT: 2cf630548d6f2b449057c7861920308958199f77b123a142c6b7c89c4982f4ed0efa2fe899914ddbf4543e70865a5e683b0721d6c8443df2e697acf31e11c8809aba94196409020a7c64d396fe136826455aec973af23a6c7733cb567f5ea550e50e0b796623a97807d042855568e3c568990cfc818c31a1bf415337f43e9baed57fada2fb2ad3c3543f2b7f2777e03f84040c1c854c310ab1cc5dc7f2a5fb213af79ac068b46c7d9475bea126adf079e2100bb57904a931faf248e0f7d5832ca83ea8a283e0136979737132afb1f4ab38d307ac0774814f4d5ecdc4aad79185c05f8a706f579b78f2c1c7004cb38e6cd22c2080735b34c3f6134955ed3bc36b1ad5c8e33209c9f3c658fb07b59b6002b2526cd8d853a5c624b7108573d7df60c827 +TAG: 3dcdabcd1c82002a551cea41921570e5 + +KEY: b33f449deccc2ef0d7616f22b4a00fcd84c51a8383782f66f1696bc6405005ee +NONCE: 6afa8baf923f986b5779ac6a +IN: b0af85a6deae5fcaa94778bce015ce2da7400ab768f3e114cc1b645fb2716789e2aeb96894fda6da5bc24fcf2466124720d6ba99e5475d77e5bcf2c2f8c8e5becf5eb73ad650861bbdeb51ba5ee789c227478934200fc18f36e4fe392c99d4c3fe0b38b40d2e84f831b8ef9bce9ac1362c755943521ecf5b5cf8fbcdf08f2d47ff7cd62838597dd342695a1b037bcede69500bf70bf1edbb40a17b44695bd8ff8bc8664b3211a6bbfdcbd1bffbfb1a2ea0141cfbc6ac841c803b137be5eeb2666c46c09cc1c4fa82be43bfd56e7a2b8ceeecb6efc1933a90213a0e1bc7aca2af35f2d1dad5f0d9002561064a699f1ce76c39d9c2224ae596e88a1517e19c2115370768d50107f3f2a55051838ae5897acf2ac0814ccd864eee2f6b5d7a6728c6ac6e6a57327102 +AD: 2134f74e882a44e457c38b6580cd58ce20e81267baeb4a9d50c41ababc2a91ddf300c39963643d3c0797b628c75a5fc39c058d319e7d6deb836334dbe8e1fe3cc5704b90c712e1fb60a3c8b58d474a73d65fae886394f8b2c029e420b923f2af4d54c9de3c7fa2bccaa1e96664ccf681cacbbf9845069a4bfd6c135c4392d7d6be338eca414e3a45f50510718e2a5a3e5815eafa0c50172cf5f147510645d2269929843bbbab682deb5823d4cdf42bd250bdbd20c43e2919d7a6e48973f43a4cab73454b97cdca96721ebd83b6dbaaec7e12cf0dae678a57c431b81421657037dd47dccbee73a41f56495fd7c25c75744fe8f55cbd1eac4a174d8f7dd6f6ba57b3e53449a9ce7806517e3e07cf6546a0fa62c7b1fa244d42eee64a3182461792edb628e567b23a +CT: 0fe35823610ea698aeb5b571f3ebbaf0ac3586ecb3b24fcc7c56943d4426f7fdf4e4a53fb430751456d41551f8e5502faa0e1ac5f452b27b13c1dc63e9231c6b192f8dd2978300293298acb6293459d3204429e374881085d49ed6ad76f1d85e3f6dd5455a7a5a9d7127386a30f80658395dc8eb158e5ca052a7137feef28aa247e176cceb9c031f73fb8d48139e3bdb30e2e19627f7fc3501a6d6287e2fb89ad184cefa1774585aa663586f289c778462eee3cd88071140274770e4ed98b9b83cd4fa659fcdd2d1fde7e58333c6cf7f83fe285b97ad8f276a375fafa15f88e6167f5f2bfb95af1aefee80b0620a9bc09402ab79036e716f0c8d518ae2fa15094f6ea4c5e8b283f97cc27f2f1d0b6367b4b508c7bad16f1539325751bd785e9e08cd508bdb3b84 +TAG: 1976d7e121704ce463a8d4fe1b93d90f + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + +KEY: 0000000000000000000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: "" +TAG: 530f8afbc74536b9a963b4f1c4cb738b + +KEY: 0000000000000000000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 00000000000000000000000000000000 +CT: cea7403d4d606b6e074ec5d3baf39d18 +AD: "" +TAG: d0d1c8a799996bf0265b98b5d48ab919 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +CT: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +AD: "" +TAG: b094dac5d93471bdec1a502270e3cc6c + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 76fc6ece0f4e1768cddf8853bb2d551b + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbad +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 3a337dbf46a792c45e454913fe2ea8f2 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: a44a8266ee1c8eb0c8b5d4cf5ae9f19a diff --git a/external/boringssl/crypto/cipher/test/aes_256_key_wrap_tests.txt b/external/boringssl/crypto/cipher/test/aes_256_key_wrap_tests.txt new file mode 100644 index 0000000000..92d3a049b0 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/cipher/test/chacha20_poly1305_old_tests.txt b/external/boringssl/crypto/cipher/test/chacha20_poly1305_old_tests.txt new file mode 100644 index 0000000000..d40b21cbbc --- /dev/null +++ b/external/boringssl/crypto/cipher/test/chacha20_poly1305_old_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/external/boringssl/crypto/cipher/test/chacha20_poly1305_tests.txt b/external/boringssl/crypto/cipher/test/chacha20_poly1305_tests.txt new file mode 100644 index 0000000000..103c196244 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/chacha20_poly1305_tests.txt @@ -0,0 +1,578 @@ +# Test vector from RFC 7539 Section 2.8.1. + +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." +AD: 50515253c0c1c2c3c4c5c6c7 +CT: d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116 +TAG: 1ae10b594f09e26a7e902ecbd0600691 + +# Test padding AD with 15 zeros in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef0" +AD: "1" +CT: ae49da6934cb77822c83ed9852e46c9e +TAG: dac9c841c168379dcf8f2bb8e22d6da2 + +# Test padding IN with 15 zeros in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "1" +AD: "123456789abcdef0" +CT: ae +TAG: 3ed2f824f901a8994052f852127c196a + +# Test padding AD with 1 zero in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef0" +AD: "123456789abcdef" +CT: ae49da6934cb77822c83ed9852e46c9e +TAG: 2e9c9b1689adb5ec444002eb920efb66 + +# Test padding IN with 1 zero in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef" +AD: "123456789abcdef0" +CT: ae49da6934cb77822c83ed9852e46c +TAG: 05b2937f8bbc64fed21f0fb74cd7147c + +# Test maximal nonce value. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: ffffffffffffffffffffffff +IN: "123456789abcdef0" +AD: "123456789abcdef0" +CT: e275aeb341e1fc9a70c4fd4496fc7cdb +TAG: 41acd0560ea6843d3e5d4e5babf6e946 + +# Test vectors from chacha20_poly1305_old_tests.txt, modified for the RFC 7539 +# AEAD construction. + +KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6 +NONCE: 000000003de9c0da2bd7f91e +IN: "" +AD: "" +CT: "" +TAG: 5a6e21f4ba6dbee57380e79e79c30def + +KEY: bcb2639bf989c6251b29bf38d39a9bdce7c55f4b2ac12a39c8a37b5d0a5cc2b5 +NONCE: 000000001e8b4c510f5ca083 +IN: 8c8419bc27 +AD: 34ab88c265 +CT: 1a7c2f33f5 +TAG: 2a63876a887f4f080c9df418813fc1fd + +KEY: 4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007 +NONCE: 00000000cd7cf67be39c794a +IN: 86d09974840bded2a5ca +AD: 87e229d4500845a079c0 +CT: e3e446f7ede9a19b62a4 +TAG: 356d9eda66d08016b853d87c08b5c1b3 + +KEY: 422a5355b56dcf2b436aa8152858106a88d9ba23cdfe087b5e74e817a52388b3 +NONCE: 000000001d12d6d91848f2ea +IN: 537a645387f22d6f6dbbea568d3feb +AD: bef267c99aec8af56bc238612bfea6 +CT: 281a366705c5a24b94e56146681e44 +TAG: 59143dab187449060a3ec2a1681613cc + +KEY: ec7b864a078c3d05d970b6ea3ba6d33d6bb73dfa64c622a4727a96ede876f685 +NONCE: 000000002bca0e59e39508d3 +IN: b76733895c871edd728a45ed1a21f15a9597d49d +AD: cc1243ea54272db602fb0853c8e7027c56338b6c +CT: 1fb9b2958fce47a5cada9d895fbb0c00d3569858 +TAG: 219b4252deb16a43b292165aabc5d5ce + +KEY: 2c4c0fdb611df2d4d5e7898c6af0022795364adb8749155e2c68776a090e7d5c +NONCE: 0000000013ce7382734c4a71 +IN: 0dc6ff21a346e1337dd0db81d8f7d9f6fd1864418b98aadcdb +AD: 0115edcb176ab8bfa947d1f7c3a86a845d310bf6706c59a8f9 +CT: dad65e4244a1a17ce59d88b00af4f7434bd7830ffdd4c5558f +TAG: 7ae32f186cf9ec59b41b764b34307d4f + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a5919a + +KEY: a8b9766f404dea8cf7d7dfaf5822f53df9ccd092e332a57f007b301b507d5e14 +NONCE: 00000000c7f2f7a233104a2d +IN: 4d6faeaee39179a7c892faae3719656cc614c7e6ecd8fcb570a3b82c4dace969090338 +AD: c6d83b6a56408a356e68d0494d4eff150530b09551d008373d6dee2b8d6b5619d67fdb +CT: a15443f083316eef627a371f4c9ac654d0dd75255d8a303125e9f51af4233ff4ceb7fe +TAG: 63c2b4e0973096299488b0a66ffa54c1 + +KEY: 5e8d0e5f1467f7a750c55144d0c670f7d91075f386795b230c9bf1c04ba250bc +NONCE: 0000000088049f44ba61b88f +IN: 51a1eebcc348e0582196a0bce16ed1f8ac2e91c3e8a690e04a9f4b5cf63313d7ad08d1efbff85c89 +AD: 5d09bf0be90026f9fc51f73418d6d864b6d197ea030b3de072bd2c2f5cab5860a342abbd29dba9dc +CT: 35aa4bd4537aa611fd7578fc227df50ebcb00c692a1cf6f02e50ed9270bd93af3bc68f4c75b96638 +TAG: 4461139c4055333106cf7f7556fd4171 + +KEY: 21a9f07ec891d488805e9b92bb1b2286f3f0410c323b07fee1dc6f7379e22e48 +NONCE: 00000000066215be6567377a +IN: c1b0affaf2b8d7ef51cca9aacf7969f92f928c2e3cc7db2e15f47ee1f65023910d09f209d007b7436ee898133d +AD: dfdfdf4d3a68b47ad0d48828dc17b2585da9c81c3a8d71d826b5fa8020fee002397e91fc9658e9d61d728b93eb +CT: 8ff4ceb600e7d45696d02467f8e30df0d33864a040a41ffb9e4c2da09b92e88b6f6b850e9f7258d827b9aaf346 +TAG: b2ad07b86aca1b3ab34033c12d6a08cc + +KEY: 54c93db9aa0e00d10b45041c7a7e41ee9f90ab78ae4c1bba18d673c3b370abde +NONCE: 000000003f2d44e7b352360f +IN: 1241e7d6fbe5eef5d8af9c2fb8b516e0f1dd49aa4ebe5491205194fe5aea3704efaf30d392f44cc99e0925b84460d4873344 +AD: f1d1b08dd6fe96c46578c1d1ad38881840b10cb5eae41e5f05fe5287223fa72242aea48cb374a80be937b541f9381efa66bb +CT: 027b86865b80b4c4da823a7d3dbcf5845bf57d58ee334eb357e82369cc628979e2947830d9d4817efd3d0bc4779f0b388943 +TAG: 6de01091d749f189c4e25aa315b31495 + +KEY: 808e0e73e9bcd274d4c6f65df2fe957822a602f039d4752616ba29a28926ef4a +NONCE: 000000001b9cd73d2fc3cb8e +IN: 3436c7b5be2394af7e88320c82326a6db37887ff9de41961c7d654dd22dd1f7d40444d48f5c663b86ff41f3e15b5c8ca1337f97635858f +AD: d57cfbe5f2538044282e53b2f0bb4e86ea2233041fb36adb8338ded092148f8c2e894ef8766a7ec2dd02c6ac5dbab0c3703c5e9119e37c +CT: 9b950b3caf7d25eaf5fca6fa3fe12ed077d80dcd5579851233c766bb8bb613ec91d925a939bb52fb88d5eda803cfe2a8cda2e055b962fd +TAG: 0887ec7d5e1a4e532746ec247a30825a + +KEY: 4adfe1a26c5636536cd7cb72aa5bded0b1aa64487ad0e4078f311e8782768e97 +NONCE: 00000000d69e54badec11560 +IN: 19b3f9411ce875fcb684cbdc07938c4c1347e164f9640d37b22f975b4b9a373c4302ae0e7dfdeba1e0d00ced446e338f4c5bc01b4becef5115825276 +AD: bda1b0f6c2f4eb8121dcbd2eebd91a03ae1d6e0523b9b6f34b6f16ceca0d086654fb0552bfd5c8e1887730e1449ea02d7f647ae835bc2dab4bbc65b9 +CT: ea765a829d961e08bacaed801237ef4067df38ad3737b7c6de4db587a102a86fc4abbaabea0ee97c95ca7f571c7bab6f38cbae60cd6e6a4ce3c7a320 +TAG: a27f18846f5a4f7fcc724656c91cf4f3 + +KEY: eb3db86c14b7cc2e494345d0dfb4841bbd3aa1e2bc640cca0c6c405520685639 +NONCE: 0000000088b54b28d6da8c81 +IN: f75c0a357271430b1ecff07a307b6c29325c6e66935046704a19845e629f87a9e3b8aa6c1df55dd426a487d533bb333e46f0d3418464ac1bef059231f8e87e6284 +AD: 34b08bb0df821c573dcb56f5b8b4a9920465067f3b5bf3e3254ea1da1a7fc9847fd38bdfe6b30927945263a91fa288c7cf1bee0fddb0fadf5948c5d83eb4623575 +CT: 146ec84f5dc1c9fe9de3307a9182dbaa75965bf85f5e64563e68d039a5b659aa8863b89228edb93ff3d8c3323ab0d03300476aa4aca206d4626a6b269b2078912d +TAG: 854cbb42bade86a09597482c8604681a + +KEY: dd5b49b5953e04d926d664da3b65ebcffbbf06abbe93a3819dfc1abbecbaab13 +NONCE: 00000000c5c8009459b9e31a +IN: f21f6706a4dc33a361362c214defd56d353bcb29811e5819ab3c5c2c13950c7aa0000b9d1fe69bb46454514dcce88a4a5eda097c281b81e51d6a4dba47c80326ba6cea8e2bab +AD: fe6f4cbb00794adea59e9de8b03c7fdf482e46f6c47a35f96997669c735ed5e729a49416b42468777e6a8d7aa173c18b8177418ded600124a98cbb65489f9c24a04f1e7127ce +CT: 911ead61b2aa81d00c5eff53aeea3ab713709ed571765890d558fb59d3993b45f598a39e5eff4be844c4d4bd1ef9622e60412b21140007d54dcf31b2c0e3e98cf33a00fd27f0 +TAG: 2865d2a26f413cc92416340f9491e1be + +KEY: 3b319e40148a67dc0bb19271d9272b327bc5eee087173d3d134ad56c8c7dc020 +NONCE: 00000000ce5cf6fef84d0010 +IN: 27b5627b17a2de31ad00fc2ecb347da0a399bb75cc6eadd4d6ee02de8fbd6a2168d4763ba9368ba982e97a2db8126df0343cdad06d2bc7d7e12eec731d130f8b8745c1954bfd1d717b4ea2 +AD: a026b6638f2939ec9cc28d935fb7113157f3b5b7e26c12f8f25b36412b0cd560b7f11b62788a76bd171342e2ae858bcecb8266ff8482bbaed593afe818b9829e05e8e2b281ae7799580142 +CT: 368fb69892447b75778f1c5236e1e9d5d89255c3d68d565a5bba4f524d6ad27de13087f301e2ef4c08f5e2c6128b1d3e26de845c4ac4869e4c8bd8858ad0d26dec3b5d61a9e3666a3911ba +TAG: 1414f1b91966340417c38226ccca9d3d + +KEY: 43bf97407a82d0f684bb85342380d66b85fcc81c3e22f1c0d972cd5bfdf407f4 +NONCE: 000000008b6ba494c540fba4 +IN: 4b4c7e292a357f56fdf567c32fc0f33608110d7ce5c69112987d7b5a0bd46d8627a721b0aed070b54ea9726084188c518cba829f3920365afc9382c6a5eb0dd332b84612366735be2479b63c9efc7ff5 +AD: 1e0acf4070e8d6758b60d81b6d289a4ecdc30e3de4f9090c13691d5b93d5bbcef984f90956de53c5cf44be6c70440661fa58e65dec2734ff51d6d03f57bddda1f47807247e3194e2f7ddd5f3cafd250f +CT: d0076c88ad4bc12d77eb8ae8d9b5bf3a2c5888a8d4c15297b38ece5d64f673191dc81547240a0cbe066c9c563f5c3424809971b5a07dcc70b107305561ce85aecb0b0ea0e8b4ff4d1e4f84836955a945 +TAG: c5ca34599c6a8b357c6723ee12b24da8 + +KEY: 12fc0bc94104ed8150bde1e56856ce3c57cd1cf633954d22552140e1f4e7c65d +NONCE: 00000000d3875d1b6c808353 +IN: 24592082d6e73eb65c409b26ceae032e57f6877514947fc45eb007b8a6034494dde5563ac586ea081dc12fa6cda32266be858e4748be40bb20f71320711bf84c3f0e2783a63ad6e25a63b44c373a99af845cdf452c +AD: b8be08463e84a909d071f5ff87213391b7da889dc56fd2f1e3cf86a0a03e2c8eaa2f539bf73f90f5298c26f27ef4a673a12784833acb4d0861562142c974ee37b09ae7708a19f14d1ad8c402bd1ecf5ea280fab280 +CT: 9d9ae6328711fb897a88462d20b8aa1b278134cdf7b23e1f1c809fa408b68a7bfc2be61a790008edaa98823381f45ae65f71042689d88acfa5f63332f0fba737c4772c972eba266640056452903d6522cefd3f264e +TAG: e84211b6cfd43543f8b1b4db07a494d1 + +KEY: 7b6300f7dc21c9fddeaa71f439d53b553a7bf3e69ff515b5cb6495d652a0f99c +NONCE: 0000000040b32e3fdc646453 +IN: 572f60d98c8becc8ba80dd6b8d2d0f7b7bbfd7e4abc235f374abd44d9035c7650a79d1dd545fa2f6fb0b5eba271779913e5c5eb450528e4128909a96d11a652bf3f7ae9d0d17adbf612ec9ca32e73ef6e87d7f4e21fe3412ce14 +AD: 9ff377545a35cf1bfb77c734ad900c703aee6c3174fdb3736664863036a3a9d09163c2992f093e2408911b8751f001e493decc41e4eeeed04f698b6daed48452a7e1a74ec3b4f3dcf2151ca249fa568aa084c8428a41f20be5fd +CT: 229da76844426639e2fd3ef253a195e0a93f08452ba37219b6773f103134f3f87b1345f9b4bf8cfc11277c311780a2b6e19a363b6ac2efe6c4cc54a39b144e29c94b9ebbde6fd094c30f59d1b770ebf9fcad2a5c695dc003bf51 +TAG: 55e025a1eb87bc84d4be00c775c92ad2 + +KEY: 4aeb62f024e187606ee7cc9f5865c391c43df1963f459c87ba00e44bb163a866 +NONCE: 000000009559bd08718b75af +IN: c5d586ceece6f41812c969bcf1e727fe6ff8d1ae8c8c52367c612caa7cdf50e0662f5dffc5ea7d3cc39400dfe3dc1897905f6490fd7747b5f5f9842739c67d07ce7c339a5b3997a7fb4cd0d8e4817ff8916b251c11ef919167f858e41504b9 +AD: 51f5b503b73a5de8b96534c2a3f2d859ece0bd063ea6dfa486a7eec99f6c020983f7148cccb86202cf9685cc1cc266930f04e536ad8bc26094252baa4606d883bd2aeed6b430152202e9b6cc797ff24fc365315ed67391374c1357c9a845f2 +CT: 252ea42b6e5740306816974a4fe67b66e793ebe0914778ef485d55288eb6c9c45fa34ac853dc7a39252520514c3cb34c72b973b14b32bc257687d398f36f64cc2a668faffa7305ab240171343b5f9f49b6c2197e4fbe187b10540d7cdcfa37 +TAG: ab1d8a5a1f3eda9b5609c0028737477f + +KEY: 9a19e72f005cae1ae78b8e350d7aabe59fc8845999e8c52fad545b942c225eaf +NONCE: 00000000d9dae2ea8d2ffc31 +IN: 2110378d856ded07eb2be8e8f43308e0c75bc8a3fcc7b1773b0725b7de49f6a166c4528e64120bdf7c9776615d3ce6feeb03de964a7b919206a77392f80437faceb6745845cafc166e1c13b68e70ca2a1d00c71737b8fcbbbd50902565c32159e05fcd23 +AD: 1cd73b72c4e103afbefd7c777e0480f3f5e68c60b85bd2e71ef5caebb175d7fc6535d39f38f92c24f2eb0fe97d878ed3d5967c0bb4394a5d41f7d34cda6e1523d3848f049cde554a7d31e1afeab5d3e6150f85858335cbd28c8a7f87d528058df50eea06 +CT: 5f009fbce4ec8e4ca9d8d42258b1a3e4e920b2fbad33d5e9f07557d9595e841025193b521ba440110dd83958e8ee30219d952b418e98a6c624894aa248aedc0678f2d263e7bfaf54ca379fef6c5d2f7ac422ea4b4369408b82d6225a7a2cf9a9f46fd4ef +TAG: 1c6bdff7d8b9554dc7bf40e50b37d352 + +KEY: ba1d0b3329ecc009f1da0fab4c854b00ad944870fdca561838e38bad364da507 +NONCE: 000000008a81c92b37221f2f +IN: 6289944ffa3ccea4bf25cd601b271f64e6deb0eba77d65efb4d69ca93e01996e4727168b6f74f3ccf17bd44715f23ceb8fc030c0e035e77f53263db025021fd2d04b87a1b54b12229c5e860481452a80a125cb0693a2ba1b47e28ee7cbaf9e683c178232c7f6d34f97 +AD: e57883961b8d041d9b9eeaddcfd61fa9f59213f66571fadffffdd1498b9b014f1ef2e7e56c3044d7f9fa7a1403a1169e86430a2a782137093f5456e142aad03a5f7a66d38009dd01b7fc02c9cf61642dedaf7cc8d46066c281ee17780674c3a36eae66c58d2d765075 +CT: 9c44d9135db0dbf81c862c1f69bec55a279794cdd29a58e61909aa29ec4c120c9c5a508d856b9e56138095714a4bb58402a1ad06774cf4ecdf2273839c0007cb88b5444b25c76f6d2424281101d043fc6369ebb3b2ff63cdb0f11a6ea1b8a7dafc80cdaef2813fa661 +TAG: 689a141bc11159d306dad7a4ecf6ad9d + +KEY: 0cf8c73a6cffc1b8b2f5d320da1d859d314374e4a9468db7fd42c8d270b7613a +NONCE: 000000003c4c6f0281841aff +IN: 4434728d234603c916e2faa06b25d83bad3348990ecde2344368d1a7af1309bd04251bb2e0b72044948f8dea33cce2618283b6af742073a9586b26c1089335fe735141e099785a1235810a3a67ff309e2f0ce68220ba0077ad1a5dc1a4aef898a3b9ff8f5ad7fe60149bd0bd6d83 +AD: a38d09a4f1c9241623c639b7688d8d35345ea5824080c9d74e4352919db63c74d318f19e1cbb9b14eebd7c74b0ad0119247651911f3551583e749ea50ff648858dcaaa789b7419d9e93a5bf6c8167188dbac2f36804380db325201982b8b06597efeb7684546b272642941591e92 +CT: bdfbfea261b1f4c134445321db9e6e40476e2dd2f4e4dbe86e31d6a116d25830762e065b07b11a3799aab93a94b4f98c31c0faeb77ec52c02048e9579257e67f5a6bae9bc65210c25b37fc16ee93bda88fd5f30a533e470b6188c6ce5739fa3e90f77120b490fc1027964f277f40 +TAG: 780cc54bb6f1c9b78545c1562cd9d550 + +KEY: 69f4e5788d486a75adf9207df1bd262dd2fe3dd3a0236420390d16e2a3040466 +NONCE: 000000006255bf5c71bb27d1 +IN: c15048ca2941ef9600e767a5045aa98ac615225b805a9fbda3ac6301cd5a66aef611400fa3bc04838ead9924d382bef8251a47f1e487d2f3ca4bccd3476a6ca7f13e94fd639a259ef23cc2f8b8d248a471d30ac9219631c3e6985100dc45e0b59b8fc62046309165ddb6f092da3a4f067c8a44 +AD: 0c83039504c8464b49d63b7f944802f0d39c85e9f3745e250f10119fa2c960490f75ae4dced8503b156d072a69f20400e9494ab2fa58446c255d82ff0be4b7e43046580bc1cf34060c6f076c72ea455c3687381a3b908e152b10c95c7b94155b0b4b303b7764a8a27d1db0a885f1040d5dbcc3 +CT: f0bb2b73d94f2a7cef70fe77e054f206998eacf2b86c05c4fa3f40f2b8cebf034fe17bcbee4dea821f51c18c0aa85b160f8508bd1dc455cc7f49668b1fb25557cdae147bf2399e07fcacaca18eccded741e026ef25365a6b0f44a6b3dd975ee6bb580f5fccd040b73c18b0fbf8f63199ba10fe +TAG: 2ecccea4607d14dbb2d2475792aeb468 + +KEY: ad7b9409147a896648a2a2fe2128f79022a70d96dc482730cd85c70db492b638 +NONCE: 00000000a28a6dedf3f2b01a +IN: 791d293ff0a3b8510b4d494b30f50b38a01638bf130e58c7601904f12cb8900871e8cf3d50abd4d34fda122c76dfee5b7f82cd6e8590647535c915ae08714e427da52f80aef09f40040036034ca52718ea68313c534e7a045cd51745ec52f2e1b59463db07de7ca401c6f6453841d247f370341b2dbc1212 +AD: 9a6defddb9b8d5c24a26dd8096f5b8c3af7a89e1f7d886f560fabbe64f14db838d6eb9d6879f4f0b769fe1f9eebf67fcd47b6f9ceb4840b2dba7587e98dc5cae186ef2a0f8601060e8058d9dda812d91387c583da701d2ba3347f285c5d44385a2b0bf07150cbc95e7fcfa8ae07132849a023c98817c03d2 +CT: c2f109d6d94f77a7289c8a2ab33bc6a98d976554721b0c726cbf4121069473e62ba36e7090e02414f3edc25c5d83ac80b49ad528cda1e3ad815b5a8c8ae9ad0753de725319df236983abd3f69ab4465d9b806c075b1896d40bdba72d73ba84c4a530896eb94ffccf5fb67eb59119e66a1861872218f928cf +TAG: 17ec6cf2b172f01e3c456ad047196805 + +KEY: 48470da98228c9b53f58747673504f74ca1737d7d4bb6dbf7c0cba6ca42f80b9 +NONCE: 0000000056fb4923a97e9320 +IN: bc6626d651e2b237f22ee51608ddcffeba5f31c26df72f443f701f2b085d6f34f806e29673584cb21522179edb62a82427d946acabce065b88b2878e9eb87ed1004e55ef58f51ec46375ac542c5782725ff013136cb506fcf99496e13fcd224b8a74a971cc8ddb8b393ccc6ac910bd1906ea9f2ed8a5d066dc639c20cd +AD: df8ab634d3dca14e2e091b15ecc78f91e229a1a13cba5edd6526d182525ec575aa45bc70fb6193ffcd59bad3c347159099c4f139c323c30a230753d070018786b2e59b758dd4a97d1a88e8f672092bef780b451fd66ba7431cbb5660ea7816cdf26e19a6ebb9aadc3088e6923f29f53f877a6758068f79a6f2a182b4bf +CT: a62e313ecf258cc9087cbb94fcc12643eb722d255c3f98c39f130e10058a375f0809662442c7b18044feb1602d89be40facae8e89ca967015f0b7f8c2e4e4a3855dbb46a066e49abf9cef67e6036400c8ff46b241fc99ba1974ba3ba6ea20dc52ec6753f6fc7697adbccd02b0bbea1df8352629b03b43cc3d632576787 +TAG: d29a8968067aeb457ffc114c3a9efb95 + +KEY: b62fb85c1decd0faf242ce662140ad1b82975e99a3fa01666cac2385ab91da54 +NONCE: 000000002f4a5ca096a4faf8 +IN: 03b14f13c0065e4a4421de62ab1d842bffb80f3da30bf47d115c09857f5bdd5756fd7c9ac3d9af1c9fb94f2640f7f4386cfba74db468e5288dbe4dd78bfe4f69e41480ca6138e8beacc6eaa3374157c713cfa900c07dd836eaecc8827fa3e70e052ae09e8473e2ae1a10b1bb669ef60a8dd957f6553daa8114918e17371f2ac327bd +AD: cfe3b7ab7550b0e8e2e8235fa0dcef95647ce6814abd3dc3f5a3bd7d6d282504660c34ad8341e4d11402c7d46c83a494d7ddb105e1002979023e0e3dc2978c9ae53e10eb8567e7a02b60e51e945c7040d832ca900d132b4205a35034fed939a1b7965183c25654931a9b744401c4649c945710b0d9733b87451348b32ba81de30ea7 +CT: 8965db3d3ae4fb483208f147276e7d81b71a86e7202ffc9b1eaade009bc016838dc09ca4bcf30887b2f4243fbd652cd90ebed1ceef8151ff17ea70518d03b0f2a24960aa7de9b30fa65c2e2d57360061aae6d9376e984e9fcd5e5dd0911a4bc8deca832ffb76f252bd7da523076593ba6b174f7d9fb0377e066ecbb6638036241e86 +TAG: 28a5284696ed82714eaa94c9ebe6e815 + +KEY: de9c657258774d4ebc09d109a0fc79d66493ae578797cac4eb8830a6a4b547e0 +NONCE: 00000000b5e35fe3398efa34 +IN: 4d68fb683aa4f4c7a16ba1114fc0b1b8d8898610fa2763e435ded8771b3651078bef73d4dfd14e76a34cd5eb9ef4db4ead4da9e83f4ce50fe059977b2d17d687c29335a04d87389d211f8215449749969f7652dc1935a0f9a94538dc81dc9a39af63446a6517609076987920547d0098a9c6766cf5e704883ea32feaea1889b1554b5eb0ce5ecc +AD: 436ea5a5fee8293b93e4e8488116c94d3269c19f1d5050def23d280515457b931bbed64a542b317cc5023d648330a4b7adca14dd6f3783207b94f86ccaa0a0ac39b7db00ac87a99e3cd8a764ed9c75da8454479636ab2b29e770b166a5b75cacc425c919bf1ce9ac34afe6b4425c3d9fd2e48bc81e7d15516d60e592bfcc2ebefb660f0995f2b5 +CT: 97a97b8f0f5420845ae8d57567f9bba693d30e6db916fad0b971f553ad7d993f806f27ab8b458d8046062ced4778c004b4f958a4436141637c6039963308dea2f54008b7feab79650295ed41bf9e65e1a2d75ab1c7b2a70ebb9e9f38d07a9a672d3e95ea78afe9ac02f2566b48b0251aef6eeeca8bd15bd8d43b559426aa9d15d960ee35cb3edf +TAG: 4ef49e8a0c2ef85826d7f03e81c577f2 + +KEY: 6885bd333c336c7672db8ebdf24c1a1b605c5a4ae279f0f698162f47e6c73401 +NONCE: 00000000f0c4a213a6168aab +IN: fa905a2bfa5b5bad767239fb070a7bc0b303d1503ecd2b429418cc8feba843e5444ed89022fdb379c3b155a0f9ceab2979000a0f60292a631771f2fde4ef065aa746426609082969530a9c70ad145308c30ba389ea122fd766081511a031ce3a0bd9f9f583c7000b333b79ac004fbde6ec3eb2d905977ff95dcff77858e3c424fe8932a6a12139e6ec8d5e98 +AD: 8ded368f919efb522bb6a9ad009e02ffbc6a16536e34d95cdb34f1153d7cb7b0f3c2b13dd05cedae27cfe68ec3aca8047e0930a29c9d0770c1b83c234dcb0385deae7ae85da73a5f8de3dfb28612a001f4e552c4f67ae0e2ec53853289b7017a58591fd6f70b0e954876bb2f7ec33001e298856a64bb16181017ba924648c09fc63c62eff262c80d614679bd +CT: 0cb3d6c31e0f4029eca5524f951244df042fc637c4162511fea512a52d3f7581af097eb642e79e48666cb1086edbd38c4777c535a20945fabc23e7c9277e2b960aac46865f1026eb6da82759108b9baece5da930ccfc1052b1656b0eadaa120ed0c45ad04b24ae8cdb22ceab76c5f180b46a392ab45b1b99c612546e6b947f4d5c06ad5abee92ff96345ad43 +TAG: fad7d5a5193dfb121c68529ba8c0c35d + +KEY: fbc978abb1240a6937ccc16735b8d6ed5411cdbc1897214165a174e16f4e699b +NONCE: 000000007968379a8ce88117 +IN: 1a8196cd4a1389ec916ef8b7da5078a2afa8e9f1081223fa72f6524ac0a1a8019e44a09563a953615587429295052cc904b89f778ef446ed341430d7d8f747cf2db4308478524639f44457253ae5a4451c7efca8ae0b6c5c051aaa781e9c505489b381a6dcba87b157edc7f820a8fbaf2a52e484dc121f33d9d8b9ac59d4901d6ed8996ed4f62d9d4d82274c449cd74efa +AD: 3913cd01299b8a4e507f067d887d7e9a6ded16dd9f9bb3115c5779aa14239fd33ee9f25756d45262dc3011069356425b5c81a4729594e17c9747119f81463e85625d5603d05e00f568b0c800bb181eb717be8d7a93166a504ce1bc817e15530c5bd2b3df1d4222245ea78a38bc10f66c5cf68d661503131f11af885c8a910b6dce70bc3a7448dfae00595beb707fe054d3 +CT: d152bcb4c24c3711b0fad28548dc4db605bbc89237cdbea7dbf956b8855d1161a0781f27bd56d798141e2ace339955efb98fe05d9b44cd011e645106bf47726183958cb6df34ce5766695f60bc70b6fe0fabb9afa009a8ef043dbf75f861881368fa07726625448fe608d578cdc48277f2dc53eaaf1bdc075269a42f9302a57cad387a82c6969608acacda20e1cac4596c +TAG: 96ae06cd7c72456e5568a42317046158 + +KEY: 77d1a857fbadfe01aba7974eea2dfb3dc7bf41de73686aece403993e5016c714 +NONCE: 00000000fdd913a321c40eb0 +IN: db8915bfe651e2ecb3ce0b27d99a6bfa7a7c507cfcb2987293018636c365a459c6a138b4428be538413db15bda69e697cbb92b154b7f4d2cbb07965225aa6865d7dcd1ba2c17c484b00b1986fed63e889f25a4966dc3ed4273f1577768f665362d7d3e824484f0dded7f82b8be8797ad951719719365e45abbf76324bc7d657799d4d4f4bb1dba67d96ab1c88519a5bee704f7214814 +AD: 3cb2c06c20cb0832bbacebfc205d77393ca1816346ea2681de4d3ab1fadb774ad273e4713290454496f5281ebc65e04cfe84ed37cd0aedc4bbe3decbd8d79d04a4e434876650e0d64309e336bfb10e924066a64acb92260b2dbd96735d03af03909aa6a80a6e89fda81037257aec21fe9be7e91a64e88e0a58fa38ecba4c4c4cffb61958f3c486cbb0b1d0b0014a2d1d3df248eec1ca +CT: acb825e6023b44b03b2efc265603e887954e8612b2ee134bdcb61501cfb9492952bf67be597c3a005b09af74d9e421a576d2c65e98104780feab838d8cb1bd135452ea39dc8907a4c1a6a9161805e4fa3e16989e6a418a7eea2582bf895da967028eab7c95d846a6de4b9980785814cf00484baa2f6de609912fff689bce6e854261ffe866bd8e63274605c7c5ad677bd7897ade543e +TAG: bcf523a9bcf772e157941753c6d7401e + +KEY: b7e9b90dc02b5cd6df5df7283ef293ed4dc07513d9e67331b606f4d42dec7d29 +NONCE: 00000000a6c191f6d1818f8e +IN: 2ada0e3c7ca6db1f780ce8c79472af4e8e951ddc828e0d6e8a67df520638ff5f14a2f95a5e5931749ae2c4e9946ae4d5eb5de42fb5b77d2236e2e2bd817df51be40b1b8a6c21015a7c79fe06dba4a08b34013dfa02747b5f03930268404c455dc54a74d9c6e35485e10026da573cb41cd50b64cfafe4cfcdf3c9684ef877e45d84e22bd5e15fa6c8fd5be921366ff0dc6fe2df45f7252972c9b303 +AD: 0f4269ed5ef0bfff7be39946a4e86e8bf79f84b70cd0b14fecb7be3c071316ce86de3d99d6871e0ba5667d9d7bba7dcaba10cb2a36668b6c3e2fb6c102938b75008bb9c213ebf9b85b5e91a802df0d31d7f11d764b2289f6225212694ab6b7c0e3ff36e84245d9f4f43fc5f98e654dea7ba9bd918658879c5bb4a1642af0d83113e3cf935d3c0d5208318f66f654eb17d8c28a602543e77ad3e815 +CT: 22586fe7338e99cdaad9f85bd724ba4cfe6249b8a71399f9a3707b5c4323b8d96679568dfc8d230aefb453df596e13eb3e8a439249bd64bc93a58f95089a62b94f6562b821c83d91f56c55147381e9de4beb4ae81bd6fe7caef7e7e9a2078f2fba8f3e70d4910da9accc92b8e81a61b0fefbece4bd89443e66e8ddda8e47a66a62f17fd0e7d0a4852ce1a4d43d72a0b5e8914bbec698f060f2b092 +TAG: bd05336ed6426de412aac37661953052 + +KEY: 6b2cb2678d1102f2fbbd028794a79f14585c223d405e1ae904c0361e9b241e99 +NONCE: 000000007b3ae31f8f938251 +IN: b3cb745930e05f3ab8c926c0a343a6eb14809fd21b8390a6fcc58adb5579e5432021765b2d249a0ecf6ba678634c4f53f71495865f031ee97aa159f9ead3a3fcb823ee5238bdf12706a9c6137d236e2e7110ce650c321e41daf0afd62bab2a8fe55d7018de49a14efe6d83a15b2f256d595e998d25309f23633360f5745c50c4e5af8ccc9a8a2cb47064105a023e919c7795d2dc331d3f2afb8c42e5c0bcc26d +AD: 1c32fd3df22b3e440e2a3c7a7624990194cb16a5f74af36f87fd6ca7d410ce9064316a2d091945deef7d9b35ceec8396069307caced2b80afd7d53ec479c35cedf2dfd4c95c3dd8400f71ad34028c6e4f8681d93d0774064ba38f3fb9b0c1dfa1f5f0c7d20676a5911d999fb6a1d41367a8e99d852bf3d3b7b3f4c233249ed1ca135389a674ff48232ded3f6800a97b6d409c40e6cd70d09bf9d2ad25d9b9485 +CT: ef70c7de98ab1d4ad817024a970be463443640eb0cd7ff234bdd00e653074a77a1d5749e698bd526dc709f82df06f4c0e64046b3dc5f3c7044aef53aebb807d32239d0652dd990362c44ec25bf5aeae641e27bf716e0c4a1c9fbd37bbf602bb0d0c35b0638be20dd5d5891d446137e842f92c0ee075c68225e4dbacb63cc6fb32442b4bcda5e62cb500a4df2741a4059034d2ccb71b0b8b0112bf1c4ca6eec74 +TAG: d48657033095db3f873c33445fec8d35 + +KEY: 4dbc80a402c9fceaa755e1105dc49ef6489016776883e06fcf3aed93bf7f6af7 +NONCE: 000000002358ae0ce3fb8e9f +IN: 197c06403eb896d2fa6465e4d64426d24cc7476aa1ae4127cd2bd8a48ce2c99c16b1cbf3064856e84073b6cf12e7406698ef3dd1240c026cbd1ab04ee603e1e6e735c9b7551fd0d355202b4f64b482dd4a7c7d82c4fe2eb494d0d5e17788982d704c1356c41a94655530deda23118cba281d0f717e149fbeb2c59b22d0c0574c1a2e640afad1a6ceb92e1bf1dde71752a1c991e9a5517fe98688a16b073dbf6884cfde61ac +AD: cf6ce7b899fb700a90d2a5466d54d31358ecf0562e02b330a27ba0138006b342b7ed6349d73c4c5c6d29bde75a25089b11dac5b27adea7e7640ca1a7ceb050e3aae84a47e11640a6e485bd54ae9fdb547edc7313d24a0328429fcffd8b18f39880edd616447344ebeec9eadb2dcb1fa7e67179e7f913c194ebd8f5a58aea73b0c5d1133561245b6d9c5cfd8bb0c25b38ffb37db5e2de5cdded6b57355e9d215cb095b8731f +CT: aa87f9a83048b6919c8f2b050315db4e2adae4a9c2ca0109b81961b520e63299dcb028cec0b9d3249a945ee67dd029b40f361245c740f004f8cf0d2214fcfa65e6124a3e74b78aa94345c46fdc158d34823ed249ee550431eaae9218367321cdd6e6a477650469bb3cc137a8f48d9cf27934b16703608b383d2145659922fb83bb2e7ee2ef938a90f2ff846a4a949129b1fb74dde55c5ae013c2f285de84f7dac7d1662f23 +TAG: 298f84c8312029a7b1f38c5ea6021f57 + +KEY: 9e4a62016dae4b3223fed1d01d0787e31d30694f79e8142224fe4c4735248a83 +NONCE: 00000000263a2fc06a2872e7 +IN: 5a46946601f93a0cee5993c69575e599cc24f51aafa2d7c28d816a5b9b4decda2e59c111075fb60a903d701ad2680bb14aeda14af2ae9c07a759d8388b30446f28b85f0a05cd150050bd2e715ff550ebbd24da3ebb1eac15aba23d448659de34be962ab3ab31cb1758db76c468b5bb8ce44b06c4e4db9bd2f0615b1e727f053f6b4ffb6358d248f022bcad6ca973044bed23d3920906a89a9a9c5d8024ec67d7f061f64529a955ce16b3 +AD: 4cd65f68f9f88c0516231f2a425c8f8a287de47d409d5ecde3ad151e906b3839fb01bb91a456f20ea9d394d4b06604ab1f9009ef29019af7968d965d1643161ab33a5354cda2fdc9f1d21ec9cb71c325c65964a14f9b26eb16560beb9792075a1597394000fd5f331bd8b7d20d88e5f89cf8d0b33e4e78e4904bb59c9c8d5d31ac86b893e4a0667af1be85fdb77f7ec3e2594a68048d20c2fb9422f5879078772ee26a1c560cbcbb2113 +CT: e944bb2ab06d138ad633c16ce82706ecf0ef5d119be1f3460c9ce101d9c4e04ef1677707fca40d1f8ca181e07273707b06624d6d7063c3b7b0bb0151b757b3e5237fb8004c161233d8bc7e5f28ea1c18da1874b3d54c5ad6ff0835eed35c8853704585cf83996e5e7cec68180af414e04f08134d3b0384ebdf0393c9310b55d8698fe10cb362defc0995e9a13b48b42cff61ffd9fe4c3c8c6dab355713b88f6e98a02e7231a0c6644ec4 +TAG: 6234e81e089b779d0d509d14e566b5d7 + +KEY: 18ca3ea3e8baeed1b341189297d33cef7f4e0a2fab40ec3b6bb67385d0969cfe +NONCE: 00000000b6aef34c75818e7c +IN: ef6d1bb4094782f602fcf41561cba4970679661c63befe35ff2ca7ad1a280bf6b1e7f153fa848edfeffe25153f540b71253e8baba9aeb719a02752cda60ea5938aab339eead5aabf81b19b0fc5c1ed556be6ad8970ea43c303d3046205b12c419dea71c4245cfedd0a31b0f4150b5a9fe80052790188529ab32f5e61d8ccde5973ed30bdf290cbfbd5f073c0c6a020eac0332fced17a9a08cef6f9217bd6bef68c1505d6eed40953e15508d87f08fc +AD: f40f03beaa023db6311bad9b4d5d0d66a58d978e0bcbbf78acebde1f4eb9a284095628955a0b15afc454152f962ec3ea2b9a3b089b99658e68ede4dee5acd56672025eb7323bcbc6ba5d91c94310f18c918e3914bbbf869e1b8721476f9def31b9d32c471a54132481aa89f6c735ab193369496d8dbeb49b130d85fbff3f9cb7dccea4c1da7a2846eef5e6929d9009a9149e39c6c8ec150c9ab49a09c18c4749a0a9fcba77057cdea6efd4d142256c +CT: c531633c0c98230dcf059c1081d1d69c96bab71c3143ae60f9fc2b9cd18762314496ab6e90bf6796252cb9f667a1f08da47fc2b0eecda813228cae00d4c0d71f5e01b6ce762fa636efffe55d0e89fdc89ba42521cc019ab9d408fcd79c14914e8bbf0ea44d8a1d35743ad628327e432fdcfeb0b6679ddca8c92b998473732abd55dba54eefff83c78488eee5f92b145a74b6866531476fc46279d4fde24d049c1ce2b42358ff3ab2ba3a8866e547af +TAG: e3b4192f6e50528c4f4f70267f094c56 + +KEY: 95fdd2d3d4296069055b6b79e5d1387628254a7be647baafdf99dd8af354d817 +NONCE: 00000000cd7ed9e70f608613 +IN: 0248284acffa4b2c46636bdf8cc70028dd151a6d8e7a5a5bc2d39acc1020e736885031b252bfe9f96490921f41d1e174bf1ac03707bc2ae5088a1208a7c664583835e8bb93c787b96dea9fc4b884930c57799e7b7a6649c61340376d042b9f5faee8956c70a63cf1cff4fc2c7cb8535c10214e73cec6b79669d824f23ff8c8a2ca1c05974dd6189cfee484d0906df487b6bd85671ce2b23825052e44b84803e2839a96391abc25945cb867b527cdd9b373fbfb83 +AD: 24a45a3a0076a5bcfd5afe1c54f7b77496117d29f4c0909f1e6940b81dde3abacb71ec71f0f4db8a7e540bd4c2c60faee21dd3ce72963855be1b0ce54fb20ad82dbc45be20cd6c171e2bebb79e65e7d01567ad0eeb869883e4e814c93688607a12b3b732c1703b09566c308d29ce676a5c762a85700639b70d82aaef408cf98821a372c6a0614a73ba9918a7951ea8b2bb77cd9896d26988086d8586d72edc92af2042ff5e5f1429a22f61065e03cfcd7edc2a93 +CT: 40c6318d9e383e107cdd3e1c8951562193c3ef64ee442432a63e2edefc78f32ab07772aeac172cb67ecf4d21f8b448423527bbeb9d8ddd0b46bdb27f74096ceb24e41963b4cdca176676a75bdbe3abc270b349ac0c6cbd9c3a5cd5bce20202fc5cc0c1bdd4fd25e121e0a24bd7bbeb9b19b1912467bf5338ee2ce88aa383c082b42cc399c9654ca325f35523e81438beb3f8926be79c378822d7c8f785614408a5f7cac49e4543188725643e6c1a70b46d0ec400 +TAG: 874875c9a0ba3060a0680291c3dc85a2 + +KEY: 6ae1102f84ed4dc114bb9d63f4dc78d7dbb1ab63f1659dd95f47940a7b7a811f +NONCE: 00000000c965d578ba91d227 +IN: b82a8a9209618f1f5be9c2c32aba3dc45b4947007b14c851cd694456b303ad59a465662803006705673d6c3e29f1d3510dfc0405463c03414e0e07e359f1f1816c68b2434a19d3eee0464873e23c43f3ab60a3f606a0e5be81e3ab4aa27fb7707a57b949f00d6cd3a11ae4827d4889dd455a0b6d39e99012fd40db23fb50e79e11f8a6451669beb2fbd913effd49ad1b43926311f6e13a6e7a09cf4bebb1c0bf63ce59cd5a08e4b8d8dbf9d002e8a3d9e80c7995bb0b485280 +AD: dfd4ac3e80b2904623ff79ea8ee87862268939decf5306c07a175b6b9da0eb13ac209b4d164755929e03240a0fe26599f136fb2afdffd12bb20354aa1d20e5799839abb68ae46d50c8974e13e361d87ef550fe6d82e8b5b172cf5cd08482efdef793ede3530d24667faf3a1e96348867c2942641f4c036981b83f50236b8e8a10b83ebf6909aad0076302f1083f72de4cf4a1a3183fe6ec6bfe2e73e2af8e1e8c9d85079083fd179ccc2ee9ff002f213dbd7333053a46c5e43 +CT: a9aeb8f0a2b3ca141ac71a808dcc0c9798ac117c5d2bd09b3cfe622693a9f8ca62e841b58bddb2042f888e3099b53638b88dfc930b7a6ee4272d77e4b1d7e442bab6afbde96ab0b432f0092d9ca50eef42f63c60c09e7b8de019b32ebe4030c37b8183cc1e3b913b0ce4ee4d744398fa03f9af1c070bed8cdafd65b3a84140cb4deadc70184de757332ce3780af84353f540755227e886a8d7ad980f3dd6fd68263d82e93f883381dec888bc9f4f48349aa2b4c342cb9f48c6 +TAG: f6dcad5412b95994f5e4d6829c2eba98 + +KEY: 405bb7b94715b875df068655f00513cb1ae23ffaac977ce273e57d3f83b43663 +NONCE: 000000005c6da1259451119a +IN: f9f143c0c52c94b4ba7b0608b144156a49e7b5d27c97315743d171911e3645ab7957c80924e3c6b9c22ab7a1cac4b7e9c0de84e49fd5e4a2d1ab51d764fc5670318688ec942f7ab34c331dce8f90fea6972e07f0dadec29d8eb3b7b6521ddd678a6527a962f4d8af78c077e27f7a0b2ef7eabd19e92b7f8c1e8fb166d4763ce9c40c888cf49aa9cdfc3e997c8fe1cce3fe802441bbd698de269ff316f31c196e62d12c6bb5cd93fb3c79ca6369f8c1ac9102daf818975ea7f513bb38576a +AD: 6fe6446505677bf08b385e2f6d83ef70e1547712208d9cebc010cba8c16ea4ece058d73c72273eed650afdc9f954f35aa1bdf90f1118b1173368acbc8d38d93ebf85bd30d6dc6d1b90913790c3efa55f34d31531f70c958759b2ba6f956c6fcdd289b58cb4c26e9515bf550f0fd71ab8527f062c9505cbb16e8e037d34de1756bef02a133dbf4a9c00ac03befc3fb7f137af04e12595ce9560f98b612480fcdba3b8be01db56ebec40f9deae532c3b0370b5c23a2a6b02a4de69efa8900c +CT: 1a4b073881922c6366680cc9c2a127b26f264148651b29abb0c388cf6c9b1865dba5a991e1f8309efbdb91bce44b278772c58fd41273526c33fec84beb53d1689b9da8483f71be6db73a73417069bb4cd3f195236e8d0a00d124eed3a6b6f89415b19a27fbe35774f6a1a6ee4bd4350b252b975f0db2d2eea82f4836350850d6290901e726e8af13644e2d98bc1d569c20800521e6affe976bd407049a2e6d9dd23f88d52e651391ecd2fc45b864310824aaadfa203762a77c1d64562dae +TAG: 90fcc2544880250f1c3abe8a3761ba08 + +KEY: 8c602bd94c630cd00c7a9c508067a5a9f133d12f06d9f6fe2a7b68dce4786d8a +NONCE: 00000000760de0f7b7cb67e2 +IN: c3ff559cf1d6ba6c0cc793ca09a0ba573a28359386a6ec93e1bacd8e630209e0b477a20aedec3c9cbf513ee6a1e3887112218d6155b9875f7e6c4bbba2c31972e905d19f529f4f0f9502996199f94f8728ba8d6424bb15f87fcacd88bb42c63fcc513759712bd0172b1e87c9da122f1993ffb7efd3a5c34b240dd3db89dddea36dbeb2836d9f8648f8e7cd428c0f948097af753b35f9876059e7702027bb00dc69071206e785f48fcbf81b39cc0343974ac70784a2e60c0df93b40379bea4ad8cac625 +AD: 9e14907c3a8e96c2636db1f3d78eb1f673d6ef043cbbb349467f1fe29bf60f23d5d5d1c3b133a8ad72065d822347541c13d1574baf737eb3cc3382fb479e6d5193b9c8e7d2444c66971ef099dc7f37f6cd97b9f7959d46e2cf25e8a5b3111b4d9e2ef906d905f0ee2d17587f7082d7c8e9a51509bde03d3d64338e1838d71700f1b4fcb100b5e0402969da462f26f974b4f9e766121f8fd54be99fc10beb9a606e13fbb1f960062815d19e67f80093360324013095719273c65542b0e31b1a2a3d928f +CT: 2794e6e133f6892f23837fff60cf7c28ee9942f8982ef8089db117903d0143293fdf12ea1cc014bcd8806fb83c19570eed7af522db0de489bbc87133a13434518bcfb9cda4d9f6d832a69209657a447abf8afd816ae15f313c7ea95ec4bc694efc2386cdd8d915dc475e8fadf3421fbb0319a3c0b3b6dfa80ca3bb22c7aab07fe14a3fea5f0aee17ab1302338eeac010a04e505e20096a95f3347dc2b4510f62d6a4c1fae6b36939503a6ac22780a62d72f2fc3849d4ef21267fffdef23196d88fbb9b +TAG: 7fa630c9bcb455e89f13d7a99d5e8dbe + +KEY: bd68ff5eb296c71cfe6bc903c14907f7726bcb1331f0c75f7801cd1b7948f3a1 +NONCE: 0000000065a748004b352ba6 +IN: 52bf78c00f6e5dca2fc60e2e9a52e827df97808e9cf727773860cafc89f4b64178a19b30b46ed813fe00c8f09b25a6a1b6e350d5b005122934a59bfbd5e6e0c635c84a5226c3f2f7dcf951560f18ac220453d583015fdb2e446c69c6e6fdecf2e595e04fab1b0c506e3c6bd5e4414a35f15021e97f447aa334f54a8f1ef942dec6273511b5668b696fca97188ff15ed84b2f46145cce031c1a7f00bd88bb83d90797edc46161b3fda7a2299173496d73b812139556e8b4eb318078b9eb2ae5046e83b79dd3d45950 +AD: 5557b08a5010cbc9f46bb140c2505f68684eb24889324bff44b27234fd7a95a99cfb4ff90a8f9982085b725f78ac42eca6ce7f3314e457dc41f404008681a9d29ba765660de2e05bb679d65b81f5e797d8417b94eb9aabbd0576b5c57f86eae25f6050a7918e4c8021a85b47f7a83b4c8446898441c5cc4e0229776ef3e809cb085d71f3c75ec03378730cb066150f07e60f96aec983c0e7e72bf6bf87ae42228dfda195f97855fcdf4e6d1c4479d978abcfa276d16ed60ecbfbfc664041335ce65a40a2ca3424df +CT: a5c8cf42287d4760fca755e2111817b981c47e85b0047de270ec301ca5f7b3679f4749210892b6ea6568f3a6a4344734a0efc0120ffedecf212d55cbcbb67815ac964875af45f735b70092a8f8435f52fc01b981ae971d486026fb69a9c3927acfe1f2eab0340ae95f8dbee41b2548e400805ece191db5fd1f0804053f1dbfaf7f8d6fded3874cb92d99a2729d3faaa60522060cf0b8101b463b3eb35b380fcddb6406c027d73fe701a5090c8dd531c203ce979e26b9ced3431e2b726a7244a20d9377bd62951bf5 +TAG: 82c6194de4d27aac4c54b023b9831634 + +KEY: 934fd043c32d16a88fad01c3506469b077cb79d258b5664fa55ad8521afdcaa2 +NONCE: 00000000c7091f6afbbeb360 +IN: 2bdd1fc4f011ef97ea52ec643819941c7e0fb39023c2f3c7683804a0ddee14a5d1784a5246966d533b3538edc7d8742d27061c3cab88df0318ab242102de3a54d03632eeb871b72c7e8f8065b49f4a91e95e15f3f46b29fd76b8fcea0d23570c5530e3bbb8a6aafa9ae32c1b3eac653c5ed5fdb2da5a986075808f6385870c85b1913e26042a9d8e78f5bc2ea6de5a64f8aeafa22adcffc7f6932d543c29bb3a04614783f948680e433a71573568d2ce984d249fb4fc06a9f358c76aa3e64a357f4eae924c1356bd5baccf7e0f +AD: f737dd85638eb324dd3891219c5eef7c2dd053cfd055d447a411eba304a4b27dce981d112c4540590933c153d603022c91ebd2b4a58069d27e6ca17a462ef822ca41bffa80b43a68b1b564644cb3c5a7f0fddf7a13a30ff24437fddd8ef93c6f6f205d054f81890d982bd4d4ece0b1563677e843fe48c1f54e9a57ed4da66061482712e710a401073be5080d5b8b96525bffa67de5af31d50385fbbf1a87c21bf0e0a1fdff69ec32c7b7103e0b8ee6c844245e0fc84b9f89fcce62966cea68e2871d3b82e8df424c76309fc88d +CT: dd13fbf22c8d18354d774bcd18f7eb814e9b528e9e424abc4e3f2463195e8018576565d16ab48845d11c9277f2865ebb4dc412fd5b27078f8325eadf971e6944c66542e34d9dda971e2aba70dbd3e94a1e638d521477a027776b52acf90520ca229ebc760b73128879475d1cbe1f70fc598b549cd92d8a9ac6833e500c138c56474db84cb3d70b7aa4f293a4c2b4d818b0ff9fd85918dc590a12a8c0e375c4d98b7fc87596547eb960676aad5559834588f00f251a9d53f95c47af4df3c4299175d5211779c148cfc988a5e9d9 +TAG: aeb0a4eb29886f0a7a12ec0516bd4af5 + +KEY: f9f6eb9ad736a8f66e7459fef5ec2890188dc26baf34a95f6f0384e79f5c6559 +NONCE: 000000007858dfc084fe4b0f +IN: a644ca6e7cc076e87eb2929fd257693fce0f6fb64fd632f7f07c648ebd03696c8e262e6a810d7b7c4e5eef8c65b5323c99dbba50a70b4a9e5c2a9e7315973cd67f35d8052ce9a85a206416dd3031929f4f929b13d0a5fb10cb73c65f6c0ace019da146b51c5274a099f44e3669d26add6f2ff081e886f3cf952fe0dbbe6b0534c23e307574bd35fbd657f5fcbd5dc19fb382a1dc0a2dc8285a0350f71554e4c601497749e35567dd4a273cddc9a48ce53a5f1d297fd8baf8d1b9feb35d9151114345abada4d90db947bb9a743c175f5653d1 +AD: 2048d1c2ddfb5ec385b201832c7a993f229ba72ec16d6ebf723ef0c5032b9966209a9e8a63151b40412e96b82f86728ea6588c7e8e11ac71cc8eabab8c4b54de866658d9c5011def61fb3dbe4e630158a45ea41a2ed55ebd1efb1abeda7637de6fa5fd2f151c6d2f385bf6cd002ca8b4a2896e0d65944ee913e3c784669dd201b1985ef3577f7f123a5f9bcffa176c8f557c4f729133cac518642f27d9b22ca9b97faaafe5b669a10b79ace4a7d5727df146c77ce681357d69f9c2d65b4401bd73cd113387e3b3a05d897adad7a24c485e7b +CT: 4146faffd7313f5d9f625370d20413cc62ab65f4acfa3c7ee1125b937dd7a39f638fc46c8ed004fb525698de5d8620ec153435571817c3de257b0d0e648ebb92940c86a98262d54e764f28cbdd4f7d9bea970291f2110414f62064d7229c6332236c507b3dac742e651d85a2a22fb243c0cc7cc2d016e5bea38f33f9a9ce048944a5fe8b078d71d23168e12dfe5a0f0b829771edc7073fb96032b7be471337a37aca0cf7c0cdd543eed686cd34934717fd79a3f18492eef72f9f450b880aa7e2e1b65e3b04c22e72301338b43aa32ceec2e6 +TAG: 61c6d4d6918b04fc1b72a7a0e9a3b799 + +KEY: 29b19636cdd32507fd98ec4ee26caab1a917646fb8f05b0dc01728a9f4a127f0 +NONCE: 0000000006699d245916686d +IN: 5fdf913aceab1d6dbaf7d9a29352fa8a3eb22718043a79cffa2fe8c35c820aec7c07644b8785dcf7a433b4189abb257fb12b06fae0662641011a069873c3e3c5ccc78e7358184a62c2005c44b8a92254958eb5ff460d73cd80284d6daba22c3faba046c5426fe8b7cacec64b235a8f8d3e2641e5bc378830594bcfb27c177aea745951ee5780a63705727ef42c4ad3abf556d88e3830f3db6b09e93edd09485cbf907f79de61f8dc5cb5fb7665ffa0ef53cb48702f6a81d8ad421cef20c1dbdf402b8fafed56a5361b2f93f914a2380fdd0557faf1f4de +AD: 39116c49cc13adb065b92cb7635f73d5f6bf6b5ccbf72a3f65a5df6bd4a661105015358d9e69f42e98aed795e8161282bc113058b7ef3b9e23fcd8eeab34a392e03f4d6329c112cb968385ec52a7afc98bb8695785af6b27b700973cc952630b7247ce226b4fbb99b8a486370bf6345d4516c52c64e33f407c4f2d1ba90545c88732d98bbd97972ac5e94c694624a9b3782b0099824651cb7567914d25b3e13181a791dbcd40e76e836b3350d310a52151bf835d3c357c9871482c2928e8404c6e533406d4d6fa8f63366f2c4ed828141f1ff00f01a536 +CT: 01e237220b619054a1f3670928fe67d40484b5af40fbd04d032500aac5acaa3b4584dd99a58c390627636a50de5d744f76a56a33205f9e3b00e16162eb47ff3333e1e208ca200f1a5338a86e17bd92dd2d16af8bb022a7dc05b923d019e05247f1a0d0b4bfcfce58dd6d83830705707676d55739abee89fcd5cb94b8fde006a5da02df64b00a467f45970b5ca440f22319b9735a55d454b9fba0588fef0c59d3d83823eba6e0601a96e10233826c5adeea6b2a51d386a07a9e047ad405b23d4c3d89f30c31e3199f0c8f927bfac43ceea1f969de0a8c0f +TAG: b9fec6da464c7b85b2a4726694562fe9 + +KEY: bae06b9b5456707551c7b0e207aae02a19b4848ad8ca4ce40705bf8c856a6e52 +NONCE: 000000009c27065c3ef2d522 +IN: 50cdd88137ff428a88e87b5845be4924f6387537bb5c0b654c80107ab5698db75b2e131848e7aec156d31aed0766d31c379fece4095d38264c6d5945974d25f729c3b0ba11ea853e9cebdb6f03bb670fce08adff74d0a8f02d633fb34e0fb7337a8e66e1c12084d914fb6173b8105684db822752c6751a372bb16690284d661b8b8bc6a6dfbddf45ebc2219596f9f2f878c118df69030de38b4d99dde43b9b9e20a3dab691645dd518342f49b06a0fe0a397adf261e99f07af5b0b3798b1022ba0939c42a54d3b93641cffa3c2e174bce9ab7ad7e7c7924308d1a77a +AD: 5d5590db1bd316eb7a0e30e4c7a6dfdbef9d3287fdb8d824389599c3c2ee262b2192eb5b9708e66e22dbc7eca83fa1a995da3ce64c86fe5aa08b826d476dc439497e2d12e2702c63c8d27aa7f09fedee816dc8bffe1351d53271a34d4292b613b7efcedb7e3cf3e6ad389eef12471e9e20e38e7ae22a323abbadfe8f2e84271bffb1819feb4f77b82843cb8757cfae293631bc6d39669107e7015c85d7343ffa6fc1bbe6f5ab4de30cd752a281e03061ea89de2a3f5e90e20da22fd6e8525c100738667f42212b2cf45fcb23bbb54b21c117484b22c6e514685314df +CT: 66b7f69ac49fab4e5975aeb6fa9287d8eac02ac312c4de78f77f59da16cbcf87274e66801c4b862c33ea79cdc76528862bb2956c06db8b8acfac4794ebf39e35ac03cc73a4351a4ff762f681a48d6f25cad36e2814c9b5c40b9ae92509e58429106847789454d376836936bebc7a80e6c66e7aa52936d6b361378a41f849ad4e48f9ee2d3e92217a908fa8eb35736ac8ada7d32ae05391f2d807be3512543c36138a5fe660dd4cd4cd184bb43b6ba6bc0bae634e2fa9669304cd510ed5103f630068ff76d3375738de60a381842b421477e25a490cdd6894b2704125 +TAG: 94118ccc68de1921d480aab43d1ef0d1 + +KEY: 2cb374cb048c168f2e43597f028d9e73cade1b458284ffc260d4fc6b9011c414 +NONCE: 000000009fb909169bc9f4e9 +IN: 39eb929482784b463546f5d84f80510f2019923d465b99d194246d68c7ae343f91971d8f7059cebb86aa5dd099289aa648248b8c5ca04e66ac5e9bf06776e3883495397618a0227f035666806e636836b47d3d2d255a49db79866cf00d9ddabda259c4f968a1e01e651c7811cebbee2ee71803ea1d9d23487eb221f2d9555756800aba5e6abbefd6fb72b3151cc99ced599cd86df2a9b1ce94f89f347eeb124d9e7f0d9cc48d3dedd819e6d3dbac57ecee199547b266116a2035c9acc4c8ca3271ac74952372897c4a5f2cb84e2d81817fec9d6774f6d8a5b2021684132db4fca3 +AD: 0c7bd4f3a30ee944ccf9489181e6911684dcffad4593a9b65a67dfc80718c69b35897d01281016b7731e12c15cad8482e79458e08a755622e3f3f22a23ef6c8487a36ad1771ba06c641f06f85de0db3776cc6df06ad8fe3b4d60d58508de943083f17cbb9dc0d390ac94d8429e8c6fcfe063f424fbde0f62f6a7f91a626d195dc498a6e69bd93109c4e9ba13e7330aba456d710a4b0cc279d4045660406e26d61dff70d4a33c4f1052869f9248024e7a0f85f1effb32f6f7ccb1f860f3ef04e8f7b29096e6bcf9d4b3e0ce703e9bf228fdf515c2ff9cbabd16987be0f9babd3d8a +CT: 91ddadb86b7ebef798ddaa59da51d71316fcf6c9678143178227d778750dc9827fc6cc21e605c505023e6db25849df7fb6fc1ca4d223aa215f8c85b724643c83bf8218815a9f9e2952384e0ca6a80a3760b39daf91a3c6154c4728c2371fd181fa3764753d0b0c23808a82cd8f0497246e3a0f17f8906a07c725d2891ce968a9d432c2b102d85c05510b28e715bb60d0403a77490e7f18be81218bc4f39287b9bb09f50227dd2f55e4fb70c4438da8ba3c8ffbced87d90155913faa9979fc57e6cbeddfaba3d3ab4163c0eebc7d94279c27d3ed56338893dba542eaefba30f8c3b +TAG: 8980e8e4fe796428b733f4f8e1954a45 + +KEY: f0f16b6f12b3840bbd1c4a6a0811eef237f1521b45de9986daec9f28fca6485c +NONCE: 000000007ac93e754e290323 +IN: 0530556424d823f90a7f1c524c4baa706aad2807e289e9479301e3e7a71f2a5e14e6232ea785f339c669af2e6d25f1d5a261096a548d23864945c3a589b67b09b0304a784d61b42b2419139485242e0d51fcbe9e8fed996d214de8717e6a71f8987ccad65eb92e66707034a5ae38e6486e26eb4374c565aad5df949dab209f7f7bcd8eb6fc52761a26cfe5d01fd349e59f4042e6dbe6b232f9301b971dee121d8aa1e62d40f043a42f3aa859d867eb809b1ced5ae1ec62cacf94a69fafd0631a8b5dfd66d855900fb295eec90ae5fcbf77beae267a79d24081bb322d8c4e0630fed252541b36 +AD: 13bfcc17b810099cda31ca53a1323db9b07633ceb2088a42263a4cbd6a4d47978776005c9a20203319c3a3ae434e9a26fb541047dc9df38dc36c095267272e203d0b24d119a70a7e96041b6d82b7c4d5570e1e4a1cf2f6e44ae63fe005a1f5b900778c482f7bd89e2e02305e35b8f61b7bb2c78a13aebfce0145d1c5aa0bf1d10d23616d5a3a446de550302f56f81dc56fe4f3700f14242688d9b92d8a427979b403c8de8c493a2cde510eaf6b285e6675b173aa0314a386b635c7577d5aff0d868a0cb3f73c8d2005f8c7c9dab5a060ef80102c9d4a4af988838afe87aff04c0689e8c3c7f9 +CT: 2c14c3931e98e84507c4c165c2ed47ad4a178f0e216cd7ac2453bbbf9f85dd06bd8ef54a9ff1fd3dd8e0cafb635d8f2de861a0db5b14d03f17aaea8c89b3010797c71c13a0e666899d7ff6e53c4f08be8ddb3e37688b5afa088079b6c7519b833e16560073e699530302028a3496e05edddec01a23a4c7983956250e8d9e616f7b940856955cde81c1efabf6b7b92f153d03f4cd17e7f7d2907670cfc84d45c1d7936775a3fce47968504278ffaecacea0871b227f250e2979516f6fa310fec0d8df1af7872e5a534e82870aa05f43ef0a455846b93ce938064fa33e92de262e4156dae56775 +TAG: 16c972829819b8fb030b2c5f40dab717 + +KEY: 3792943c0396f1840496917ce8ad89608385007e796febeea3805f3f4cbeccf7 +NONCE: 0000000023b2f9068b2c4c85 +IN: be6b67eb943ee7b5c785cd882f653e73a8f75b4a41a2a7c56ae5a10f729caf39948fe48ad0e51240e2e7aa43193c7ec6ce7f4909fc94c9f99e38e6a0ad7e98eb29c5c2e61c99e9cbe890f154185cec213a74725d23c1a4e4d0cb9b1a36b78c87e5eee20d2aa29aae80d4759eb0c51c5dc3a95bdbbf7e14eb434419a6c88a954ac03d0c98739f4211b8732acd71c297f578b8cb64ccac45f7235ddc7f2a3f5f997525c1ed39dc550126cdf9cedaf55425489085e91b170be6205a5a395f2dd4084a3e8dbc4fd8b13252f7effae067b571cb94a1e54aba45b1b9841308db0cc75b03cfce4ddafe89ce20f2d1 +AD: 7eb6d7b7bbaaa3c202a4f0f1de2263767169eb4a64853240d48c0f8d5d31b08d5baf42977614a57aad99426cde76d242cb37d2956d8c77dc4fd62a3abf30e8ac6cd58c8ef35e67497022960138c57787818892460f3bfc16e37ff388b1edc6ce2bc53c22717edc7a03d4c78b0dbbe9121c7fd8a3e3993b87a4fe389bff13bdae3b349de0b6db561602c53f746022aeb4483c723b67825042f4af20b7dd1e6031cf54215266295c524ac8e1370424c5c5e607fb3e23e97c8eebe64656775edf616422a8b974e1acf13ab45c9a367a7dd9b2d62f48bbc05819b65eccb813ca813f57b22ee4c280dbb5a9d8d5 +CT: 0b316ab2bcf5359900fa4082d5d253b49ad94b70e3fab544f98bd111cbcef6766cf953deec08cae1f489fe12f7acc0032db8a6b0c0eee0c206ea5fb973feaebf90f690e840094db5e13fdd7157ba127368c995b426529435a1bcdd1f14ce9125b8a0e4c96b6ec09e3c36a180adf81941c002d19c19d53c2009be803b987504606b7d43bdee5e0b32ff23c466b6cccfcd0d4e88fd1332e73712b5ab725c1a383e584f34f80daff29d285ae5e43cf1d0cc7a828e75c25daced3a581a93d7a50f313b33f38dddfaa23cd5b9914797db820ee2400d52bf5fa982277fe9b5881ac42981633b3957b0e935051828 +TAG: c549aa944d6d97e52e0793ed572682c0 + +KEY: fe4be6054773f634356ac328591fbc6f833b0d1beeb38dd5b6feb7481b4489d4 +NONCE: 000000000b3f16f898a5a7d5 +IN: 76ced1ade6d1ef4069afddb32e7432d4ff2fd06685121f7b16464e7a72d365744f547d2ccf53486310e38b42d8bacaf711e54c5458d2d68c4dbcc8de31ab6732f4430e88a64565f5b287640775aaa2af1cc461d3e415bb275c6246b1b58517aa72667eae291a2982eda175d1b22c5a58e6fec2b3743d55712f201ca24ba5c0ae8c25724871b2ec2fb914a8da5a52670ab9b43a83b8568ce74db5c634061cb80530c8070c38b8f48c33ba136cb9f2158ee7eda8b65f2192fc94d1291f182f101795b7190c74b319d2d3e02a97c824d9c9471a83797e4936310b207e3a1e0bcf75f7c3e3ee48a747641cdc4377f2d55082 +AD: 834cd775cbefe4b33a3ca53a00c06a3c4a666983e4115a029f15729460daa45d1505e95172d3695625a186b28b8be173a925af04665f209267b3c5123e8be13da447ee1ae856bb0925f35aaa76e04a7bca8460f76c2024de2149f38a8cfba81694b854885d72568105571b6b213a0bc188a44cc7fe13153cbf261401b238cf12a95e23cb56f240114f16e2f1e3a514615aab4449c0c49e4d900b0e17d1a8dabb53d43dca32fa052d576b73dd9b40856b515d6d7efc2a5c17e0ebcb17bd59dc86f22ce909301a2652f134e82ef0e4519487ed12d51536024f2ae8f75d937c42d003076e5dea8de0c684cda1f34253d8fc +CT: f8defb6fe95dfec499b909996a1f75a198a90e4d6c6464d00a357a555311c42fe92dbbc4b79c935e4f0b1a95e44fdbc1380bebabca28db4dd0d2870daaafc38ef27908c3509e945714801cc51f1a07b2430c74fa64f2a7c2f7fd1551d258c9c3be020873fc1bf19f33ab6c660911dcf2317195d0efee82d20ec26d22611f9cf86c51a64e28b3a1f344500018e0855c88dae3c07acaeaa10b60388484dce93e16e6e1a6e69e899806648a92568c8780e9f4baacd98cbb353ac2f908e775d92303cfab843f15be0e0c322a958802fb1a60fcc7631f151f4c2b8cb965d2d296acef250275a2fecc0cea803ce7c058b12dd2 +TAG: baf9a51180f172e5c0cc2c946ce55055 + +KEY: a288b11ce5382ec724ce4ab2d7efa8e777e91ebd04367935e15f9dac483e9596 +NONCE: 00000000874144dbf648b325 +IN: 4c9195280a79a509919af4947e9e07231695fd7c5088539f23936ce88770ce07d9ad3ae4a463b3a57d0634d3a77ceaadf347a334682b04be8e58b8e86fb94a1f93255132b8cdb0df86f5bea354eea4e8315fea83e3fdf6e58aa9f26e93caa08e5e2551a94bd916a51fed29ec16f66800cda6a0aa24ec308bf5fb885afba272685de27c1edcdd3668048ef07b06e90d464a8aa28664903cac45e154e8e1e39c257e1ff506b9d95cef4f300bb73b899e7828602c3c1d290b8cf55ee5fd72ecce9e6efc9293aebf674a70e2a7673e75629c12950622dff71d3ec0992e57776c788c6927d30b4e24b749191c3ce8017f0ada6276e43720 +AD: 04abe8588c8c8c39a182092e5e7840442bd1c1149da102c4ee412bd8b82baa5087ef7291b5cd077c177c42770b0023e0e462b06e7553f191bcb0315a34918dcdbffe2b99c3e011b4220cc1775debcc0db55fa60df9b52234f3d3fa9606508badc26f30b47cdb4f1c0f4708d417b6853e66c2f1f67f6200daf760ceb64ffc43db27f057ad3ee973e31d7e5d5deb050315c1c687980c0c148ee1a492d47acfcd6132334176c11258c89b19ba02e6acc55d852f87b6a2169ed34a6147caa60906ac8c0813c0f05522af7b7f0faddb4bc297405e28ecf5a0f6aac6258422d29cfe250d61402840f3c27d0ce39b3e2d5f1e520541d2965e +CT: 0afce770a12f15d67ac104ba0640aab95922390607473cbda71321156a5559906be933fb0980da56f27e89796eaa1054f5aacf1668d9f273cc69071b9e8e22af6a205a6a88f7ad918e22f616bddbb07c78913c7e056e769e6fcf91c7600c2740212e3a176e4110cac9e361a59a773457064d2dc652dd115d04f1c3756c0e1d39f6737a16b4508663e310934c49c58058b3c7b9af7bb2334c8a163608c42499658986927cda365e2aead3ac29de16e47e954383ea566f8fb245a4e5a934c767bb3bf7e0eb8a477fd0e1f61bcb238462a0d19c5cea9293ca58ade76829413216a7882cd2846323046694f78cd8b0347792ebb75abdc1 +TAG: eb9b2ee43e9a3ae1e33561800169d868 + +KEY: 65b63ed53750c88c508c44881ae59e6fff69c66288f3c14cfec503391262cafc +NONCE: 000000007f5e560a1de434ba +IN: 845ef27b6615fb699d37971db6b597930a7ef1e6f90054791eb04ddfe7252b5f88fd60eba5af469bc09661c0987a496fa540621afeec51bebda786826800943d977039dee76235248112ff8b743f25ed5f3cb0d3307f5e118d84fdbb9c3f5531bc177fb84549c994ea4496c65e5249da987dd755d46dc1788f582410266a10f291c1474f732183a2a39afe603771bb9c423fe3e8906f2be44a0c9a7c3f0ceb09d1d0f92d942383a875c0567c7869f045e56dd1a4d6e90c58d44fe0c5760bb4fd01de55439db52b56831e5a26a47de14249453a4f8e7da3cb3282c6622916197ebfaad85dd65c61e7d2d3ba626276366746f396394c1bf75f51ce +AD: 51a3588398808e1d6a98505c6e5601ae2a2766f1f28f8f69d1ccbcad18038c157b41525be58ae4527a073748b7a04809e52a5df0c7988417607738e63d7ead47db795a346b04e740186e73ccad79f725b58ee22dc6e30d1f0a218eda1791e2229b253d4ab2b963a43e12318c8b0785c20fca3abcf220c08745d9f9602f0ece544a05736d76b12d249699c9e3e99f3f13cf4e5dc13a04125c949a5b30d034b23cb364c8781964bc6c30e5e5ca9673d517ef5f35965d8a8cf1be017e343df97b6bee37b30638b154286d1f36d2f9a0eaa23cc484eac5a05b15d9efc537d989dbc8b3106c0dc1a56e97e6aec2eff54a82cf7ae9df2af46b4c860f83 +CT: 027b14197b4012256b133b78ddc94e72fb4d724fefa4ae329f5a5fa3fa784fe6d7e1e805e3f7a75557de64de506d38237b467fa577efb59e7cfe2356bed6655c5aa4e238dcfeb75c16549a0917268768a96acb5e20546a1fb7e3a7cff887f49f2cd7a135f72a98a779150f3207bf733e88861fd79eadbf77fa3bfe97bfe8b6a991cb3bcc2cde8287f7e89384846561934b0f3e05e0646e0e1907770df67a7594161a4d0763faa6fa844080932159999d528ee0558710058ce16f97d13ac9fd9bf5044191188bbfb598d0fafbdf790b61ce0781ecc04218a30ded45efd498cc9ba03562ed2b4a993ee98876b3ab7a9bc07829f1c4ca6ead98c06b +TAG: e0bf9b6837428843f5a233ee5ddb8a1e + +KEY: 4986fd62d6cb86b2eaf219174bec681bebcdef86c8be291f27d3e5dc69e2feba +NONCE: 00000000d08d486620ed2e84 +IN: 3a22ad5de387db4fdd5d62a1b728c23a8dddc50b1e89f54f6198b90499f9da3122ebeb38ebf5fdfe30309734f79aff01e3de1e196b35bffa33bae451f31f74b8aec03763f9e0861a34fe5db0b40c76e57c7fc582bfa19c94ee25b5e168270f379bf9f8a0a18bed05de256f8f0dd7c23ba2ff1c7f721409462f04cc611ad9bd4c3c9acf30742acfb9518a6375cbb15d65a1bc6993ea434894f93d4f6e05996ebc1bd56579296309a2c6b8fde95072168b5fd31927c4c0abaa056bcd16221d5f220be47591f43255013a262dce439817f534830ba82155347e5fe3101f8011b89365a6568214ed0661914e8cb3431d6c8f2347dfc1209a3eca4aaf0a111f47fe +AD: 7dd3f656a03c001b45ca0680bc3ac9d68c6e96b591d3c69eb8c65e489009d845cb331c98b82e627e06d5bf01e74c573df268c2386f12628c019951d42f55991ff20d72a7b2c45f41d0be7af428c92f324aaab8df70d900301cdf09a3d93eb711c919d34a86fff9cb078322ee2e0ad48dbdf3b7884f0f2dc5c36262c59bcfd75ac6200f59c6fcd0ce10ff5005fef5df8f0432377dfbfc1db8f559e27e1aeef3380ea3864867d36a25a18654779a751586cad3b8a46b90864ee697b08605673b8d2123433c020a21c4db243dde2420c12fd4d54a2704a0c8c376454a1b5e80fd6db89aabd56d9b421f29649e474824dfa56cb5c673c504d10be52b53751709fe +CT: c40180afd53001663ff4834110f56e6b0f178cd3c0e7f7de5d0089ee41d8403ffb98e84922706544a344d7e2625b12cf66b9c966f9f57d7b94e3e4b34e6f0aaed1763ce012782e2f5e1682e6c343fc7961fedddd0919d0b910e9923c17e36406979b256b85aec24ee352f03b48c1302eab419c83dccc5372cc059e9de596224fa70098eb32fc9579e97917b923914fa2efc30ab29b457bf14e45583b3771486bdc0876f3ea6e1a646746c4f8c5cb2641a1557c8473e6ea67d4811a67485ae9a678ff3a2408ca845c3b51957e189eef47dfc1d46bde4b9d754d7df13f828ddadb06e4ebddb5f0dafbdb28de4c5e6078926f20cdf9e97ecd58e309e640f74f06 +TAG: 2e8eb9ff4467c0f61c2abf6ca10893ef + +KEY: 7d28a60810e43d3dfa32e97c07957ec069fc80cc6a50061830aa29b3aa777dfc +NONCE: 0000000047738ac8f10f2c3a +IN: b50278ae0f0fa2f918bb9a5ed3a0797c328e452974d33cbf26a1e213aa20c03d0d89490869754abf84dbbe231d7bccdced77d53fd4527356d8e02b681fc89a535ae87308bf7fbc26197a5ea85bdb3aa033b8da5cd197ea6d72f96f63b03f4ecc7adedf399a5043776cdb32c08f30b77f34df85f8adb8e02649a04b020b03e17d445ca63e4ed73ae432c481392e031eba2f9d2f7f981d1e50917822bd6ff71c239d33444ada3523a59dfbce5457eadec1ab926c9e6c5299c7521e3f204b96901a712504fcc782e8cea80ba12a7f7e71cec3d0871899b6ca059061da037715f7d13fed01c9cade1e687b4fbb1f4ac4b040db3b43800f112fb900e4f772d61b921cbce4da6f +AD: 324292813b7df15bc070cc5d8a4bf74ead036430be63abc43304cf653959a24a91c7de5a671c50fa8a87e21bb82b069999aadfb6895d8bda4c3083d17b8ca55b9ab1511ed8c4b39d8c28c11a22ef90c08a983e3fe2d988df9e02b16a20b24f39ddb28429625f511db08298c4dc321f6c268fc836a6191df6232f51c463a397a8d8b33374abe94e62c0f5c322387e1fc4a1c1980a04a1a3c2c31b32f183a11c3268c6dca521149dc16af120a78be6627210e8ddbc44472bc24d66ce3681c7579b3d9a425212a704a4f5105cb80f0d18ee860953d10b59c114826779bbc368d7a0eece9f223e47cd8e5fd453607d101d9d9c2bd9a658d6520b87d7b4263f6d845a524a36e4 +CT: 2c217e969c04740a1acfa30117eb5b32dc573df3354f4cc3bf8f696ff905f1e640f3b2c250473b376622e0c9bda13b94640521be1ef0fc660b4c10dbe2bfc093030753e04f6aaecf813b43b61f960455974b8bb8a9b461d1e8fd3802315e863c00448f24dd38deb90e135493274eb14ccbde15c50dcad734ed815a806be6622492a84cd062e3ba567b909a205a1d0d2bedd40169697d261c7b6c2e0b1f069853fd470e8f364a142c386c439a6dbe192ded5a3d0fbf73799f588c59e58c60249d980ddcf0d9693631cd9b3f972509c3a77123d38d9e267ecad06e1208e3f1c0a69fbca7c3bb1a48fda19493d0f8f48398820057b94120f3ef97d87e9e8a1b301a2534c68f +TAG: ce507bdb0c71f8e89f5078495f7995b8 + +KEY: a76e9b916f5a67b78a5949651c8c3a9741a1bc3c41cdf85fd2c8f3e9a0616098 +NONCE: 000000000808da8292dc14e0 +IN: 9c149eeb09345c3c22462b03e49eb4dba6bc98b269b1086d752bcd8eea53b8977b238a04a994baf915591686baab90b79a3bf7d9adb2c6c2e31acd3e72f0813fb745aa5fb2e3da408f78001c9c09bd26a1a2646011b6120aaa2bbacc4a16c39fb5257b9b2ea2ad8bf70bcc9855cf11841116c2767310cf3cd49d1aa44cd505f079761e064d5bc7cea4a7173b086882a77d3fc179efc86fc4db8a373491d2ed81eabc63c950e832db17d09f474d4ec46bde47830caf26fabaa0372b81fccc449c0e19ccd630caf693a7b43bb1c408a54e03f50c44280a05ad89fb6e8f01d8ac278edf556e5d86ceb4b614fb2ef133819c6e1ff6abb86c54a135256204b5cd400b93624d3932e7c2b046 +AD: 6aeb7031e4a2e23eea93f05fdc562aa2bf43b8998bea7344377aaddc60fbdb7bcb1491d379ed0cb613ee757cfb66490db61bb431d2fad34b38ddd55bc5b22aa6c4773b9992f34b878c5663f6e8cdb5f80a17f4d312bf342492e48d1ce4c6d754076a634fece61500acf8168d47381af4faf980c6cac2bfd5da8c09b6edb0f543bf0fe02643e38d73fa37d8ae87fb66193f22e57faf4393c007d48c8631a685d520578f8f89db684fb371ea02f3a58b1e2168f0216321139472e0d03b6d90ba8aab65402e1c1ac4f9172a60e27e3d997b9b05e2f672120d6c87bcafa6d4c9b4cf8ba8a82932d92840368fc53dc5b48526103dcab5f1531038aabe89171327ac559b98a3cf4ea70bf051 +CT: 9c3faab9261a63cea9477b3269007283995b06ba77ef83d9e693f7e4ee9855550eef94855be39a7a435b6a3584b202973777c7b2482376ba47b49311947a64983b60236756ee4455d4cfada8c36af8eb06b06ba2f6b79ffb1185c89f2b2a831cfaa3855fc1841d8910908be5078352011168a67d36372d851a3217cabf593ea462dcd325cf9a4f67e85418fd5c924e9b92ab026cbee4e7ab1067066cb5949dfc699a68fe539e1abb13cec33904e5207e6963d24f5a0b770613b8b00014e791bfff88f9c25ca126127a2f8d1d1e9794efd28dce98b53e228073faae8d5047530d502184fc341321c3f55fcbf41187fc31262c325b97f519959b6a29b36c71f76f60196bb1457b77c8bb +TAG: 73b00b1705602479aab944dcc1b282a2 + +KEY: 98cd2477a7a072c69f375b88d09ed9d7b9c3df3f87e36ce621726f76e3b41a1d +NONCE: 0000000077d185aaf715aa48 +IN: 42b31eefdacab0f03ef6060156000c8195adb0976cabbe1a42bfcc09f85659c60b98638401f2d2e2facfb9a97a62926bb0cecaf3af0180a01bfb6e576babf7fc43331937a92abd30cddfa3e450f895e9dd914dea3fafd759c136d685310ebce28ac0613ccdbf30115946c9634b67510b77d0e37f07714b2ddac9d7095b8d4bd887c132c4a9127eb01c8dedb4c39c87b98a741316656f9a8d5a5b0c0ac84789aa2347a5f99ca5ad55cd1bcf98f703eb4b00badb8a8555f38b3b368db8ba7ceea94e8b219f51edce75d84166b5602156ed5962a93a51db73c59d87e906179d7a74a2a2a69d8ad99f323225c87e475d3f771b4a203a2e2b03b458401044649fa6536dfab24d7037807dcbf6518e6578 +AD: f5bb1496052a4361dddf72a288e36953a3d815d6876c013f1d6ba839e127f721b052b1f7d8ca20c7dc0386a7d459ebd7eb9fc8cb08941e6ca9ddb980f3115f65bc1928a414d441ae71dcb879d5bfe0cde0562bc37f8fde0d5291ad405c92fcbb860c43b55ac0fe663b54b3d0616aca13a5c82b7b5d34125a05c2acb5530141030e6f2aa0c8322b2c8fa307e7518918e550e9f48921c6168f094d8758e16b9f815fd0458095c4143f0922adb1840d0e685636825a9c90ee90ee537f4b8dceecbc4287c82dc9a00d7e51671e37ea284ee3ca501b1b2596459d3f592f70186f41125739e342c9f6be9241973b1414dfe5fb8cba1af82e679278cfcf95420df0c5364af4d7e72ad57d5c871fcbc35462 +CT: 7a3bf3e3ad5ae3ab71fb1f7121c3d8fb511099484b50af7ca128ee0337ed4b828dc4cde0b88dc1e8089101fa82c9beb3eb48fdcf0f5b16da441f5a3fce9a590022af95a94aed6a3e71e505f60f303c78c356f274ea85a55354078530664ecda32c80e77dc20974b3b38f4825b8fbee8c3970769a2f42c5181608a8d7d76ef4d093961b665ee42b9708fcafe2c82d3a307173e2a25ad2528c3bf83352b9265e45b70722d7cf8c9b80826d21335234ee3db69d0d37871c83222365900c96c17a7e9f5742d0bfe383be24d0d44590d4b0f29f7abe0c65daaffb968b3f2657b1eb300534eacb52ec7a6b6f9f57a50a91b1799f491361cf613c934b7f520dc4eeeb40ffc45e10be0a95e76f366d4eac14 +TAG: 69302888812eea030d621b640e7bcf7c + +KEY: 2f0f4631ab1c1bcf8f3ad0559c818d50e0af7d8cd63faa357f2069f30881d9cb +NONCE: 000000007d0ced2fdb1c9173 +IN: 6516ba1d29357144eebfa486d21decf223da3aa76ec29bbfcbe7f1eeaf4a847710e5080177f7e5a7c8b4752c219b1cc70aef4db861ba67d0fa6222d9f4a1dc756a0ba44e62906f9374a960c16198866d867854d88f528a60e212eb91645787e75685b2e215c0a41990abc344a77236ec0186ba63a664592938cc5a8ac1d3eb99c95ce00e19fbe249263083d85b052d48bfdffc01585dc57bb2a2c6c4a819604c1ec0548c6f0f78dc05e4418b36277dc07233c7532f9c289d6aed0cc6bc7df4fd0a536c497b982e2dad2c30d2db1c6545a845c5dfa83a4ac49ef06fc9c919079d3e299e31b5c3be370814ae5022ae469d3ee55246a41bd0dc4e64351cc38c3c09af0a1aee3b388a6892deff0df3f93cd92d722b +AD: 1ccfa1ececc8de1e200d0ecc19dcf67b7c96bea3a282c2bccba61035db5c14776387b8b8f58e5757deb0129d4e5e315f64df354a5985d2e47ebbbeafe0c914f7cf1d63dd0311ace19e69a8b6ff0ab25cc8df0408d22132205e89e5eb679268d82b2913e64e3f885bbf4a6d379b760b94590e3140dd7275ab4713cb56d0b716e2718f11316640cb394802862d39e77a46d0c065af3caf7dec14e887039d8aa8c3d3a8ac1ee06026f49d00b2f59d971b54735e95a51f199389a93a4fc24ebaba1f7a2eef7412f61febf79084fbf481afc6fb6b204084e5ef5df71f30506459dea074f11fc055cd2a8c0fc922c4811a849984352a56a15659b7d07a4cc90b88623638ea00c4c8bc13884df2237b359f2877aa41d6 +CT: e580093789ba17ffb46672dc326f09278aca08598d3e5458eaa53e6ed45d5c71a396e35b5ea3fe7b7c0496a734d24f1c75420694be2ff095d5172fd3407794e4b99fd7c374fbe8d1564a048614d3f355bfb5866de1a53e1a51f9f5e8312253cfd82f36efaa1898c850ca0d975ad1e8b0d9597a5a9e6516fe2a3c92efb7495557a8afc3da15b0d3e2ba58f612519836946cf2d15b898320d16a026c8c00a1be2e35f0ebe68f28d91c6c45d24c3f3c157cb132fa659b7794df883d90741fa2d2afcc4f27858e13ecd41b154a35d24947ae7361170060c107d8ecacb393ea67104b60457278a392fdf1794bab97d3b02b71a4eb015eaa38a4b4c944c2bc7cd5e329da4a1ab2937a6af81a6caa5fce752331fdefd4 +TAG: 19bbacfac768bb0ce71e39c5d4d3e9a0 + +KEY: a48b9b6df475e566aba7671fbd76772cb0eff0b12499967978ce3e25fac92feb +NONCE: 000000002ccbf0d6c40cb302 +IN: 09da1cacd001dce4f7573a065a4406fe0da04ab367a2d87780a2762e168957a88d3fa78f0a4b6978d449026e5a801d32884b6e14fdaaaf864214f928ebc03dead081fee96683ebb032362d5088c4c2a3b1e242f055f2604919f4dd551db777a258cf9da6d95a2bde249247812b9efc7985cf08707620808524d6dd3079b0b63bf0f71ea5de834ccb8b7c6a97125fd6ca49148e866d3134bbf1d8a6b714e9a80fe549c8bfefe342f41be2ba2300e0028f78cefab65274632dfdbe70bf7d655ec4036df561f2d4fc4d56a482bbe2f9f2ae279b3aa216b39afee75e53602de319484db89a51e844f38c361634e474f8f1f01c340f3f3594860d671346449c6d08ee38de22d246309bc7e4a252a29c86aa6d94b5b4fa58904c70 +AD: 1c2503d5aa1aad193f0da12874074ea0432bb76a61cd43a3017061514da0759846a0f3ae3a49fdb0b6d29f713de665beacb6568f2694112ca380d13f3c1698316866a7a7f87f1d7503a92176ab84fc08977b46ba664508a858e7525753c45511b3d2f407d5e993c6ede77f13d12975707e5195704970a89f71fc30828049f92f944f3aa93d6a5297e678e08952919beb7eac5919df1919cab3c3da6aa696a1eeab6371f310f7e81143e7d240b0213ae554524b52000306160dd4877bf13ba0f13bbe867da7c7d707f31335eef4cd942938ac890a0829ec66bd30ae01a2188a6e5ea0f17cd7dc875e17f03c0ab5dd18e36db8a1fc1f72859ee046b62368f168b3bea2234e0432c07b7d8e1b9277f21e692c513b9e816e6860 +CT: 7d35cfe4be56bd6e0e09dedcd01735b915bc1891a4d1f6a541abc4bcd0ebe89dcb8e365e5813742e8ec65777b6159422fada747da99394252baf8a046fc1b60ad79755f545f4448627b7acaf403000894f5641e78d3f946dfca29ec617f0660dcd6e8d8827e67e1022a245c595d86e60fbd176bf721b171bbe5ecaf4ae671b9f3dd3920146e6ad431bd8fc431820e19454b6ca209723d80fdbee187fca9c937c979206ae97be55f6ba7366a5608770a11d537396485eb0a66586385f4d4cf3905d1fc90831c3e136d5d513fa22be285193142994a3ed477145bacdcbdd791e8b3b88b0d4f1d18b27382550a818c4fd8884bf36f677c6c3ff5677406e510911e696af75e5b3f859bef699bdd16e6215fdb98d874025eada50 +TAG: 0fa4cb2bab84336409aa4349ab99a8bd + +KEY: 923d4b086b9e43b986f7b65e4cea6113a3d8aabefa89323c5e4d5b6f158bb7e0 +NONCE: 00000000a0f73297b87f5deb +IN: 21435e8d5c8edf0684f58c2cba4070c10b4801adf46b6c4d322eb3990a38a9ad338ad704b9df6597f3e68d66cd5b56290c8466db2231e56d6bcb9c44e1bd081f42ca2a894dad369df2bd0d2c63d6c881732d6ea22bb22b5bc9a62eaffa1b094d0845f6b966d2cb095e7b3b8bcbc15e707449d35c8df4aea30c3b7243e977fffd59c80f1c5c9af4bb5a54b9c786fbbe8d21b2b906a87a786caed841a34a3e0cc0ac3209d83c58afba19edd63622dd261532d2cfb0b49d527d8eaa0887a087f5129d897f665264b229f860363d71a88b7d49c8dc6360182b357b0662391bb41337f46010ac32b9fada2d60a2efcb99365d3b27b7ac396900d1c821d0df8b86cc9cc1f2673259a33efea610bf8e1d00d7e9db2afea21da8f58c55f799999d +AD: c853a8b39c0dc597d562f123cd221e4104b65423a062a4f4ba890ba344feb84290f61817e23330c365f58c3583ce08360d3c1171982ead5496d525ac878f23a57480a6ee39d4e65afd6268245bb982a2545fa1195427cdbbcd404cdad5198f55cce2a5a028fae435f71b15921d066e8d43766c32b2f2c3f57c0674e129607dcd3703eca529414adaee79d81fed432153cceb6f3fc53404810d8ec878f7d94be5d379d0e0e1aa9bc404b4b5d396038a9d76a5ce53c9f3759b8e50fb331858ca58cee81bfc3ee58baef5d19c402a3dc8b36370ec1ace5a4aa2527fb94b4f933a4ab8ccaaf6a5af5a779eae5667c2a24ab027e781c8d4f30c377aa5885a2fdaf6507d18cd824a847c35368b4ea984d2c3c3824a5b8ba3042e1852504a21a3 +CT: f2e21052eebbb86a4f5e803360855d8632aa727dca6f5e79dd74d7aff106e442001928d113005b030f8446f8eff2ee951db663978abe43090dd5ad2c51ba97a0ecf988c607d95e486d02524f690fa3c28d5c48c1f75c1f555e7b43fe7e46f2ca2b9fdb408ec4ba18b6cdde2af673183cb7b1a3c23ae77eddd4cac75e1ea14743fc571f8d31ce2e96787524cd48aadaa474181c096a032184574ddc25a6e0ac8441c212bc36298708e33c963ae931e6c6241d1affeef7b6ef759495df44b6ab647447693cf703569e69aa72f1def9a342b8978c1edea9703a421ca75b92cac4de14b88c693200022b8a2ed22b1c4678b99f4d695e080dd1196d7168e14f0d0f8ff880d742e97b9f6d00af1f7118e10b77c5ef3ea6c52f84a20fd6ea46dc +TAG: 9bd8b7743c056bb2334833afd6143e18 + +KEY: df73adab2768559ea983cce85453fe81d79be3b3c57f202b31b94d6635cf2e4b +NONCE: 00000000e7a87e6bf6b5a354 +IN: 0032a37abf661faa18c587fd2aa88885c061deeba81105dd221969bed5d59c7204b09b1a8c4c8de3b9f748c7fc70626ebeaca060233a57b102221b1bf0f3d9fdaaad3d2b1439c24d08f9c67f49f3c47128f92ee530abf4c4f4573bc60ae4b38109f55bca3ca9e1ba9f9fd6e34ba0d174892977a53356e1f5c88c614fe3ff3b3dd0818e7a2285412e3b37444bbe8a80942efcfd03958809a6966cda9430b2f0c9e552f4bced6e19eb3e85fc5758bd7b588297ccbed37ed94c3adc8c08ea8b058462aac9d57a939ec711bc4ecfec944d2b653b7cfc7b02a65d7057c9fdadd51b9da8cc4a3c68dae9da8b9c5319c1a2baa3d6c891c5ac4a39461484b5a01abc64df447ada24c04a4363e605eaccf339a9aa515e724206206da6d22bbd2f52e64cd7c895 +AD: f833e5ab4f8bc89167f80f576b1d6b22cdd0e30721f5f735799746cf645b6eff531d4c7b03584f3dfcb73cbd35ac42736216dc7f0de098a4f42c61ceb4b227ee288e47d697a0a76afc762f084e8fdbf9351c28340c324771c109a469341ab10ca10483ed2af5e878d7d3dc2bced2f72da3d1a25852b103ee9878e8158eb4309c1ce528f3a178ace153b6d3ae0af0d577cb3cb1540489e80427f792217ad8a09b84f027fca7ceb651b4264e98e94b4cb8a37b133390897233e8ba9103628d05b9609e8552c4a4b11e3f2fa8d56af36957390e88cba44656be3edace798cf8cdf7771bac338a256bc3cba6df97728f222f423ca7c6d149c9372d66163a98f79a234b00d4b75fb2ec860dcc2d1998105e4b9c01d68f079f3e0aa21cc534047fc7b858f8 +CT: b842eadfdf431c135bd6581d3eccae54e2267d8890036aa33dfe2d2d9715c44625441210a3a0d666d708d30588fe851ec36e10d8fa3584ed77b095149494b7c54379d62c8935e1d2b9a8f47e4759ad0b3437fdf2cc2fb6c5ea25ad10e0bdc9dc5b0517fc237eb783cc461c46665e2b1d1a5b8008dbf409ea2a63fea0276de23a32c99d92a498807a0f95e208fc6262321a78aafaf0cc3f833fff37bd4efa66f6023a25cdc6702cee3912799563d908a5183c9956a06aa71085d855dc7c809ed6e2889592b361ab3ab39060f8e419152187a794a19c2a1128882201900ea2cd597860674bf78d9720643df8701676718fd201baed4935a88e50558daf86edd08a9ab227ac7afae55c974b68de8dacad4a4d79b13ed6dfe74017a4cb9148e033436fb6 +TAG: ee1ec36804e1d5cdbddb52608c711fd8 + +KEY: 55a4be2448b464c2ea52a2f2664ed6aba865c14ea1fea77f4689331fd105c8d4 +NONCE: 00000000db37c0a405b4626d +IN: d266e66272e5d3462081b004cb42429c8b9741e9f678153754d726f6f9aa513464763c5e793b482fe512fece97585f1426120d4cefb3d0a8cc0a8db4bde93fc72c78f44d4fecca14650c660d3e285b327e7cdd813063e7e867b8a2d059a41bab70432b7f857199894da90dca3fe5272bae1ec694a1a07b60b05df275784d4975637e4673109f3ba846dfd1a048b202ed8e89973be608b91ee4743b1e759900f1443038951fe6189e806638985f3c16338c3c60695df58e621154d79bb973859c4558e9dca90470f77c73f004443ad5db0717abbe43266f90e57397b83ac34d1fef2e897e2483d5bcdcb627abd64b0d1aef525835f25e76d6e9158232cdde6dce970b59f58de8a98e653be32fb58edabbcefa5065d73afdf1c9c4fbf50c1022bd22bfcb98e4b422 +AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813bf5c501ad31e5d791c4b5b3a0a71b63fdddcc8de4b056064ef467989ecccc5d0160d403bf3a025d4892b3b1de3e062bc3581d4410f273338311eb4637529e4a680a6e4a5e26e308630a5b6d49ead6d543f8f2bf9050aa94ce091318721e1d8b96e279f34b9759b65037bec4bf6ccda6929705aeeeebe49e327e4d7a916620c9faf3765120658af34c53fbb97ec07657b3f088fcbdc401aa7949ddeda34d885018c2c23f4f0bb8218bf0d4fc90643658b4d8834f4a8c08e590c2a790995baa9e77627c342d283e454f84fcc05be15e9627a2d9be340c9d72f222bbdfc47905f56616cd9f936d49e4732f319f020513340fb8b22828db251b102b6b137c9533936d6 +CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f +TAG: 296a397d280d026fc3627f4718971be9 + +# Tag truncation tests. + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c2 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f3 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f37465 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a8413 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a841386 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a5 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a591 diff --git a/external/boringssl/crypto/cipher/test/cipher_tests.txt b/external/boringssl/crypto/cipher/test/cipher_tests.txt new file mode 100644 index 0000000000..0a940f14aa --- /dev/null +++ b/external/boringssl/crypto/cipher/test/cipher_tests.txt @@ -0,0 +1,613 @@ +# RC4 tests (from rc4test) +Cipher = RC4 +Key = 0123456789abcdef0123456789abcdef +Plaintext = 0123456789abcdef +Ciphertext = 75b7878099e0c596 + +Cipher = RC4 +Key = 0123456789abcdef0123456789abcdef +Plaintext = 0000000000000000 +Ciphertext = 7494c2e7104b0879 + +Cipher = RC4 +Key = 00000000000000000000000000000000 +Plaintext = 0000000000000000 +Ciphertext = de188941a3375d3a + +Cipher = RC4 +Key = ef012345ef012345ef012345ef012345 +Plaintext = 0000000000000000000000000000000000000000 +Ciphertext = d6a141a7ec3c38dfbd615a1162e1c7ba36b67858 + +Cipher = RC4 +Key = 0123456789abcdef0123456789abcdef +Plaintext = 123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678 +Ciphertext = 66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf + +Cipher = RC4 +Key = ef012345ef012345ef012345ef012345 +Plaintext = 00000000000000000000 +Ciphertext = d6a141a7ec3c38dfbd61 + + +# DES EDE3 CBC tests (from destest) +Cipher = DES-EDE3-CBC +Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210 +IV = fedcba9876543210 +Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000 +Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675 + + +# DES EDE CBC tests +Cipher = DES-EDE-CBC +Key = 0123456789abcdeff1e0d3c2b5a49786 +IV = fedcba9876543210 +Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000 +Ciphertext = 7948C0DA4FE91CD815DCA96DBC9B60A857EB954F4DEB08EB98722642AE69257B + + +# DES EDE tests +Cipher = DES-EDE +Key = 0123456789abcdeff1e0d3c2b5a49786 +IV = fedcba9876543210 +Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000 +Ciphertext = 22E889402E28422F8167AD279D90A566DA75B734E12C671FC2669AECB3E4FE8F + + +# AES 128 ECB tests (from FIPS-197 test vectors, encrypt) +Cipher = AES-128-ECB +Key = 000102030405060708090A0B0C0D0E0F +Operation = ENCRYPT +Plaintext = 00112233445566778899AABBCCDDEEFF +Ciphertext = 69C4E0D86A7B0430D8CDB78070B4C55A + + +# AES 256 ECB tests (from FIPS-197 test vectors, encrypt) +Cipher = AES-256-ECB +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Operation = ENCRYPT +Plaintext = 00112233445566778899AABBCCDDEEFF +Ciphertext = 8EA2B7CA516745BFEAFC49904B496089 + + +# 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 +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 3AD77BB40D7A3660A89ECAF32466EF97 + +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = F5D3D58503B9699DE785895A96FDBAAF + +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 43B1CD7F598ECE23881B00E3ED030688 + +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 7B0C785E27E8AD3F8223207104725DD4 + + +# ECB-AES256.Encrypt and ECB-AES256.Decrypt +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = F3EED1BDB5D2A03C064B5A7E3DB181F8 + +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 591CCB10D410ED26DC5BA74A31362870 + +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = B6ED21B99CA6F4F9F153E7B1BEAFED1D + +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 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 +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 000102030405060708090A0B0C0D0E0F +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 7649ABAC8119B246CEE98E9B12E9197D + +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 7649ABAC8119B246CEE98E9B12E9197D +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 5086CB9B507219EE95DB113A917678B2 + +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 5086CB9B507219EE95DB113A917678B2 +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 73BED6B8E3C1743B7116E69E22229516 + +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 73BED6B8E3C1743B7116E69E22229516 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 3FF1CAA1681FAC09120ECA307586E1A7 + + +# CBC-AES256.Encrypt and CBC-AES256.Decrypt +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 000102030405060708090A0B0C0D0E0F +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = F58C4C04D6E5F1BA779EABFB5F7BFBD6 + +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = F58C4C04D6E5F1BA779EABFB5F7BFBD6 +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 9CFC4E967EDB808D679F777BC6702C7D + +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 9CFC4E967EDB808D679F777BC6702C7D +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 39F23369A9D9BACFA530E26304231461 + +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 39F23369A9D9BACFA530E26304231461 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = B2EB05E2C39BE9FCDA6C19078C6A9D1B + + +# AES Counter test vectors from RFC3686 +Cipher = AES-128-CTR +Key = AE6852F8121067CC4BF7A5765577F39E +IV = 00000030000000000000000000000001 +Operation = ENCRYPT +Plaintext = 53696E676C6520626C6F636B206D7367 +Ciphertext = E4095D4FB7A7B3792D6175A3261311B8 + +Cipher = AES-128-CTR +Key = 7E24067817FAE0D743D6CE1F32539163 +IV = 006CB6DBC0543B59DA48D90B00000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Ciphertext = 5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28 + +Cipher = AES-128-CTR +Key = 7691BE035E5020A8AC6E618529F9A0DC +IV = 00E0017B27777F3F4A1786F000000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223 +Ciphertext = C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F + +Cipher = AES-256-CTR +Key = 776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104 +IV = 00000060DB5672C97AA8F0B200000001 +Operation = ENCRYPT +Plaintext = 53696E676C6520626C6F636B206D7367 +Ciphertext = 145AD01DBF824EC7560863DC71E3E0C0 + +Cipher = AES-256-CTR +Key = F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884 +IV = 00FAAC24C1585EF15A43D87500000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Ciphertext = F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C + +Cipher = AES-256-CTR +Key = FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D +IV = 001CC5B751A51D70A1C1114800000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223 +Ciphertext = EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8 + + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = +Ciphertext = +AAD = +Tag = 58e2fccefa7e3061367f1d57a4e7455a + +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 00000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78 +AAD = +Tag = ab6e47d42cec13bdf53a67b21257bddf + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 +AAD = +Tag = 4d5c2af327cd64a62cf35abd2ba6fab4 + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 5bc94fbc3221a5db94fae95ae7121a47 + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbad +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 3612d2e79e3b0785561be14aaca2fccb + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 619cc5aefffe0bfa462af43c1699d050 + +Cipher = AES-128-GCM +Key = 3de7b368783bd7287f2b9b731814c876 +IV = 90dedcfff100eb1f1db9d935 +Plaintext = 8d766795cadc0961c0f448c62df3827eef3a8664599b3adbaab0cfd63875bceb8f992b4f7447dca10ddd716aa0bc4fe925e1aa3e3fd1d5c430c650fe3546d6b9a24d576a857c5f04e8c0a3b149df277aa19cfa64ee235891d3b8ec0e840d268b1e70dd8a4bf97628a0c7aea38aa21eeb8fb1a8437f2abfee05e0d2c30659e312ec03d30da51b7c19073a2341c17df806e27e796d581143d39e4de8d3f8d46aa6d6fc1a98d94fa69b92dab751d930cc12de21fb1a7468af09e3c12ff6c3db3967d10cf140bc46f17a16e24b010b6cba5ebf777341c52042596ee53008389c48d9690ab9f5625795c3e588f72f7a1670b2b25a9f4eee1c8845ac90f1bf47ae4ea4b607a50aca88ed304cbb700d02d5486139b0bc81ec042e574abf986972fa008b83ef22dbfe720c2f2f6355c87c975932cec545ebed657e5e7570c503e9aa7f0b87d0b2648e421ed1d34749637c95d1e931af8925236387e50454f0ba2e22ed05f90450fad46f4eb7ddb08656511dd065c0f852a7e42f618a961a6c6bec42226c6b6043580b009ec9837cf99844cb74794a82c269ff648e0bae9ae50256a0ad98ad9f5a35057b3004ac96f469f9ee966dadc16dc47616586cf242706df96bb2f7ee43d3bd1c65d2eac7b82ef242e77ab509afb9639e5f3995380e926305729ca762c487f4411ec2a9c688b8347e5287216dbb38c3fe2281a89fcb47ee2ee7ddf79bfa3ab61cd56a00981019bbcea8aa0444eb75958e5fa56ea0036d2de4950a7db886f4a318b433bd41e00905ab158171e0ef13172293bdf70064b9dc7b243bf9dc927589bf9e99468d1cb330639dbff1850cc51929b8971b0b2ede9d06bc5f6ba39d4551b587f09bf6f8206e8f1524f55714612581d6aa45d8fb83425f84a736576deeecafdcbfbb8670d14cd2ab2a7f8b7f374c07881b7bac2605fd5ff7ff7cf43e30cf49910961a9079c0343b8601be8c3e9fe38f49fdab0b7e1a8c1536cf84e4d80d26ae5ec37570839b5cda02929221898d611525c3a88fc444167ffc532b256cdd0a8f31ff08097d75b629fab99c9e1062d1d9962b211e15ec8709934029c4934e64db8d7a2f32e23dc541be306e9a57a3419115994cbc3a8f8d5ea2a6f45b9ea9ac0e51ed0c6680fa029f4552a6c8665aab00ab77928342e7284c321e9500ad4774ef1fed0f596d5aea371fe1793271aef38cde55547f34701a525526e83a72673385a85f44db511bc87ce1f831fc6ccf8204ca4f4a20eac09897aae93684f14ede21bcaf40a09c08012b92600d6a839ebdf8bdca7b34192c6c50bad8796b3be3c375dbae6217815d2c75cc878d39b4e842d4eaa5f5df2242cf230e44a240e18e47827f089b18bf880fd41a2516eac8e6ba3fc2db64a4bc28789860d7b18d9edeae8b3059f4d945b15d0ee27b1f74842dd1df117fe83a8fdade23a47c93902eedc4d33f2dbfcd1996e6dc1458409fde2302830e8d44c58c5ae67486b9950dd938f14c38bc4c9484fdc4ded93a0f90875773453fc14d428cd6e7beb0c705d61229d2b3df09632ebb30b325fefe2aebbf2a7aa8e4ad46277ca4b8b078818b63d04e7652057f6cbbab7c43ac355537e0d3918b4a73c00dbe6b30a27ee7a6fa213d3347ae478e8edc323404b8322b9c7b0173ed61c38ed25f3576a675d527d22edd51d6dfa5767560d3a50a91226338e8c4e6436eedbcd3d2efe9dc1e686b15d2f57d553abcfda57dc316ca453a690f20148f0dfa20c1c4a58240aaf7195095fedfa56d839d0230d55ce9a8ca1b9d1acd6fe98d583148ba0f4a4e3413c76e6ec57ddb79428d3a90079f64d3321c791f60d501c3fd02c8403f0f5e6c6836bbc96430c1b48e83350c3a3cfd017f15bee3e4bb1295d821dc98b85ab3145555cce2c34a8142fe50f8db19918b514a165d12ff6301fb2296788760ac0b6d9e3a57770ad5111cde5d24b6321918cb0b0887a282b827a8749733171914b000e7d3c0edad1d42ca60da37f0698554bb2a1749f73b3120dbeaa32951f8217a781a200467d5b569d16f56fc9b7dff0ac524f03fee0617f4c692d94613b1e13b18075dc9f0d32811d4a8949a95f6b5fa46aeb83597adb409e68b2a0177c36dcc95dcb2e7dd4fb7337ff97c013364fe139e185014948fa698741d822044fa3f6978b16afd18138c845587c405ebf7a6cd1c28610ce67e992ed49e406658a0a202feed9709500d064b6f53eecfca57dd4b38363ce3aae9d59126d8ae7e140a373851188ae28c909181d0ac64770df70dd2475809350cb367825b59d521d5e457b4e36aea6dedd90a2266898b753b57fa359d43cd388e7d6c7ed90bc4c2af34ceafe88a3af6ac376fec35f1240f08af4f3eb30bc53dd68e5762e6d39e6b16f63003fbe0bee828d0d7adc58c41e857c2c44702215b202701fc696eae021af19c79e59c3e32627cd571f5db99b17f1772b5d746196befabb0b7446687827f3315b391d5dff069b1c39c00bb143218ef458e3b397e1c99640d57fc8db2e0083d3d22ed4111a8fc9e0e6f55fe6a56e946dbee43909bdd7d516fdf756ed8099ba80b1e17a5e279119345104379a36962ca9c8b2a53c414d79eb09fe79862ca749a9eabd9185ad1df57215945882f5894868a134bfc35c835e040e77ecf077d6a98a73ee022963d70b036be3fe5718280ae52c5d751211b22950c0597aaedd35af41f7dd5999e5f7ee34a37edcf97df54a46742b0252b196eaee454ff0c30685b15f8de087de208906be1d971f0fd89f7cdff2af0bdc96759d6889fba9ef092ad1c8deab0404562a7f3977d211c28dfd1573aebd5427a8773f03986101703fa19cd4ab96a381c76a747f63b63f7a9a3a08e251cdc593a024f63b443b76d17dd9e151809da3c582fbd334fa6dd0221b6d410c6a78ba95bb0154bb8999f619f2e084a6b9755ceee4ca3c7e0481a47776c8814f13054e627e37630d593bd09d5f10a049c66c9999f4b0b037e81ef70615d674c7c7975972994a053c069675fad3fae5ae3e779233b70254fb87f25d44c104afc3d5911b8b695173f9337130e39a02cf97356cb817f6cd23f55ef74dd06bd24ce5887a7001ef576262ffaa99f9bb5e3f55bda2aa0f199115909af48bb4d6b1a0a0847774515302cafebe75aad1f63362b1f38141e8721851c3ef1a247931b3b450581eb5d09027b9e3ba60ae9801d629b74991b7fd65520eac561d47115a85141d9a757bc75710bedff1630561ae05254ea541a7ff1846ed5e164834417556dd562c45543c88d8030bb56451fd5b3cbf10fb0164c5288789d2aac7e7a836e79bc3dd401a8e3e05aa6714ffb2dfddb3037c35fa1ebed62a073b2da42133f2620ae88de5e3f46cc69f2b9b3c9b88e39b8b108059ac6bd493be5f7a39f6b53ee825f4593b77ec9238f5ab804d533f48803e7d8187291ee25cfac4da5d8c9279517adfb09c422f6d704711726c73828a5082b4c7b3d85611b8f496d3e0f78c5c4f1dd1c722b1b11d55861f232beee6aaef8a00fd2eeeb45f182af191ca6de8eaa25ceda5451416fbf6d1abc0670b8c10e2815076f271044c690bdcb64856b91265bac202043a28f6bbeb807535aad4bd89e572a9427c826b170d3862f4cca70ddffb4769d6593a1cc6c42fd06cf68642835fe474a23e6f63df316f8361bab959b768d78e20c03c2a99913c162a9662bd9981eee55922f36792de0af68da04ab49dca72e3d9b0de79df828b433bcf6be073f851a36418c03a717d54d48c1014ccb793577c8393b7cb53cad6bc7060a54cc6363734f6ad388763519ca09b533078d3cfa61d7bdd4c4dd0ffe64d68d501b55903d3f4a1f310a3826ac2ca700de01d656188dcf577fd1b63e305614b8d13471f6f84a5d4b12c5e119870a63d1e3dbd39d3b5c26b09f9d80f8a59ce836b20bc933496923d278a022c00f3aac204d07d2e5075bbcef1e4820d633a3a2b35974f72a033484a91a1d6a9913239c93e5783b01833073c98f358e3465efd5087af37ad60b7285550e776d67ea7019e788776c5a456102358c32eb4e7c28096af88b9a20d8ce379ba3928a10ffd539c106f4927e7ac0f382c74017d6e4438fb128c660affd45e9bb68452de72b574eeffe3ce239d0718908c3800bc7e8ecd2fc7d9754171506017fd7868594c9373a96579fed475a28811649ce5dc8a3107bd0d8578748878ce4998684620931dc3981a2499568c2f61174c3b3fc46a7010468e8ff75c08cd43ac764d95e2ad1659f9db62e9554f811e0f43bb74779d923c8c243d12a5314d3c0c6ec84fe60e1d2b2e2b20d3e64054d62049ef9233ff55223a319c285e4e3f4c98dc95b2ca81230d7fed9bb99fd7d97430eb32c9c11647992bd85dcb47cfd58ea3e221d095bcf9374a6baa7c8333581f62b9e489282483023fdd18451f09bec764146b587209160b3d1d7a3d2e145fdb640c4bc382541e0d84255122d51a710887ebe1ccf29d41b4dd7fd7368d68ada250d3968d6f0971f0849c13c09abadb9db8b08960a18f84f0346ea0aa71227afa55b90cabc062d549b616400d36450b19adb67d7358e48c043fa1135abfca89374c906f8d1a6a845debf6b37f055d390b029c7f4524958bdf8d7e2755dde3b957f0926f9d3b8821ba96044d3cad2d637b973bfb657fcc06ff44c17965acf572ab7a0c87604c7dd1cfd136a0ad02b22e8ef320e101ea09772588e8c5b4d88f40fe1be18d27146a2b9559491949671700cebff9a709f297c2621ca9d5d1749623abc20a326ff5be55cb9435c03bf49b147b1e0a4a918bfdc3642df90b396a474f81d75c953d87b3f3b4e31fced630bd7c481c63acbb84dd31249101ac5277a36dcdfc80d8d9a2e928e9b2d65bb257bce97ccda83b187da8a7886dc96eab93d0864d88c358105f9cfe1ad0f0a8508b5b3985ff95de652e684da970b57669aa3fdfbe590a631522abe8246393639709a9a6cd549e78e3c2d1acf84643e9f554c5e076f75a5c1dce1be20a66722d0b896837b7036509ab8d473d5d2b7a8374d6a575f69d54afe3e7e18f4faf4e917be8a74e55c271b96d966e0c0b883f84b3ef2e4f278daeda2efd3ce770801d2c4bda5eb9b646deeab9fa55324e917e63e4eb6aeb4176cb4e43af3db61aea1546fbf16e76a12fcdbe726b565710e3f9866551023e5fbac0038678717e6ab4d3e92dcc53049e8cb65c00216d31a8869ff4d3539313fe2fd7ce0f53b255e3659e7dfc5f92b7627dd9ba42972f0ba72b888932d870ab97226040c4c0f4826be131fe1d2cdc21005ec2addd7796f0927501251ab26b0e5f3f9d2a1cb346a774e18bc233cc89aa69f5f70e3d5c17098eed350ec419c82837153b5c7f5813bf5918defc8df143063f3fe45125deded2b15892d5cebce589b60f2ada0f9d608983e8d107d8e6482b5f542c6650b014445e8c055aac142f16cfc59229fc9626f7aaa40cefacef777e494e13dfa93d27c201788ca9f60e572af8d65ffb513473dade5fe494cbf7377bd1ed03db2571d65af3be4b0bf27c1f069797bfb67ef0bd8a88c6286af6712c106df9c418d88054e3b46c88296a2e63894d6bee0dda8833c373d6a1b27637e1510fea3eb2fb34ae27354571369653a282a8d19f2c34f9e5ec34555b4ed24327dc5d246df13736bd41021697104f80c85bd0ae920e9aeb4e628fb8aec269d55858df149af298b06d61250b043c8a14a15f0646d0aaa18109d031c449e66dd7336044dbdec912b1bb615fae2a3df480bd64cbed74be65c8f1acac247e80bbaeb6f9dab38c6addf4f3b094d5934ef5c9749053b9159e280034e601731a12d6688ff27ee3581ae289de424d16676fb750d2ccd5b3f964dd77bdefc15bb204e2350632822384cc194cf9130f1ee81bfc3887d3366ec0b48cbbe0fe674281ae7445f03791887873659825680448f162452cef57d783821a73047078a8cf94c416850092ac772ef0b2e48517ef101ee0681b5259aa27fd56edf3c01e6dba6298ccc91b09bb304b637eccf8c673b816e74bd7f8ceffa6b17ab03df7ee9ca4098d24d044015a07df782a309cb6761528272632a6e1323c4e18284b463dfcabed708e4fc95cef133865cdbec8bfdde100621c65a92762cc3141ff37b66dea8fa6e3aad61dcbf3b512467c4773d36e58989e12a636389c1678c191137a5f7f59668c8a527dddcdd0c3fbb14cf48b8f3ea306850a5eda76c57aad06312d7bbfc18969d7b611f512358a7bdf959cc2f41de1c408133ef02b1fb2cdf8efe9973c27536434e56fc1bb4880db7fe901087b53ef3c0de18aafa47c25f1cd62c362f2e5da41c2dbff0e13adaba26c1e0829f027dc0320442e851eaed9507b70ac17180725349f6ea7b59bf39c095a9d10790e87221c7c2d24b8bca184ee95a3ef7449aad6c1d905f688498ae7a0cd1b01f76dabc342fb2be0295ca1484bece3c9b8a1b91e53de2d2587f3607a7f348f5cbefaa7a6dcf61bbbcae9444e2d25a77b016cbd1508c8cd319e9812b43b0bbca52df155d418dacb6ab1360a9e605fb53c6e20588a10bef42d884989e836b2ff16fbcdd2c1704f75dc8c1ac2cc6aeb92726f5d46e4784c70e1e249c102be6da506e5e3c2cef6a8bc4a60dac7adf3cacca8679f8f792ddc27613e44a70fd849b7617e042da46d65a3e6cf425f59b83cbae5b6e911142abd13a0a8cdf06d041435ee20e2ca417e905d2dc49c15b863ae5920ff7f9380a86bb0c86b69a000c157cd35245bf71f9dfdefbd1760af90ec3e554ebc511aebf650633221ca9157226f613f41406872765f8d7b916ff3877266f017b8d840dca0697ec3dffce7912ea9eafb62cc2f2d0a112c9bc0727444b47b62766bddf5b5f26d391f653b6894b069069979d0cf8cc7fc4143626a8420bc0a3866db3860096cc128d620ceff059d1614487004adbdf6b0c4428ac8897dcf16e6b11a692a6b465a92b40010f3480b444d4d2e24b0af8467666905c2a6233bdd6502521b621d3cdd4a5e1f268d65bf6a1879608ffd3abf635c5f0948f3cec7e087485c72b00258ba69783cfe7d611bc41c27814ef5674185791dbe626e1f276cf2c399a4eb264f19c77ee95d94252f546528f629188318e9ede65a927aafd2f2af56ff32c0ef39862d2f92268bc9400afa8ddeff591f3ef99681263a33b873bd9e01a59c8b281da30875245cbffee5268563c7f6f20b9e22d998934131dd219624d3cef6df2f3d2d6401833f72c619d6f763837141dbf93179d0f01375581ebe227185166aa7988eb9fd453d510ca6616cc013d551d23a33a4241e85aac3201284344977d496d768f5d920c5670b1d8bb608efc1b99abd261afb0a4ebe191605cc5c2e20523a13b3b94dd1fb24a27009d9a5b6329336f3516a327642386ba64c8769da1324a8a3d1f304cf0700df2b3e38215a954523e1d40ae96d0046e2929a815bf70785e94bc9b89246ab6aded60d65170eeb49b0ee0a57ee2e57db92409105c25f2d0c1a17b5556d06511bd0991a426258372c7f2b402dd533a75aa175524eb5d6b9575300b81fdb2258bd74429add8aa477bd1182db57107d411d16147defc3582861c68f5ce82e0a0316edd5d0f3cf36825a2c79a33e376cce2e63274b3b41bcbdd755845ad9ed2a3bdacb6fa3fa9484b7b60edeb1d9ef84772e78e39adca14c9fa0bb3ad1f1c17fb9449270e9b4c97b5b320839947fc73853fc58304ee9c9e86f3775f5469554d5006eb7ce9d02d5f900c771806c275ee7022e2b55d111338dd93ad51d14008df4c13d8c03fd9bb3689607e5cbdd499c3a372b487af74cb140f6300cd2dc2acda07277ea3dab57ecf09f1a8f2d6abf7c44fcdaa6dcb1f6e791164004b20b3b4c860f409c1483c7044b6fa445f7224606894e386ba08057a387b48920d4de203b1acc4dbe2b0b4cbdc3f7d7bbb097abbf81e01db09e120eab83def925a059cdb513efe6bc93f0579ebf75638df3c3d7f9eba3c36a169e9d88495c452888853640d93ee70f254f86e2d2d3fbb5e8883b36fbd2da105cf3a75cfe998068203186bb37f1d1ebead8ce1f9383b816f1da2fd0a9e01377b6ebfed4f05bec08b4ff9b90e385736fd13a3af7980c21b0dab58decea8e9545af5d0fb11bb51aeda2c8616960e8f6f84e6c2fc4f50d7e413afe030f75475509fbcf49cbe14445d267994fd3f38f41a1339f2895c0b2969a9bf9c59b85e629486c7bb5107c7a6b069793be7690f7a7c96c93b09a9d610594a156ab27a32d5557a5b1ec8920761cd2f559ad808dff3da64717ea5f10fba87b8ff2712ce322eb3c288939e0007f779a3920f45fdd533369f6f85a8cce21f91552fe03702ef81a926af0e402b418fbb25a6a3dad0ec18ec663126b3f48c341e2725abfeae865352d5ad275a9e3ca20393c64d118968023daac84bdc724a3c522d97a5878ed788cf8e44f80f8803d57584d8c8688cff24dd8c0e881b62d16ea30104d62007a4bec051da7fdc95d1df8556ebdf607383a0825ae503e24661ceb8ba773b793360c3f4ed3b761bd372570cb17e7c2030f07b0b45a7974e45ee6fcf5bd7ae9e9abde5421b42cff6af0c6eb7fc73f4deb67bb4e0b3dc9b4008da30c67071243cda649091a14b89bdacf2ae98dd230e932d9b277d6968c65e0006a8ff63f283f2cd9c21615dfd82e0b24af6ff559c97922a3d112ff0ef4af9d6583bec1f84d1aa8bbae705b9bcf458f5d93059b90fc2217ab27d0072a38aec3229d13266beb3015ac2389a06dec3120c6c04e540886091597919da293a4a8c0812d6cd336d5c5faeb64162ec0459e252d219bed78c4b6bb61c1213939bb3cca12a625ce5a45001d7408f6d40fa9466377caa43afe961b5c1602679220258fae72a8de2ac69c0dc97c90c270e306dbd8eb681ba9c092896b19a8d42665b94ff4d5b8b188f19f7c44abc8f88d4ad7b5df1cce3465de377072c70dd20dbd6779336f05ce328ad741d1e4606dce7065347df111c7d3282c8a3fa4a9458561c04d1056cd53ec5a8ddd6bd4434ac910c69cea0443fd09ee32d1256da44ab7896867a0c97fe4faa4a53b6db5cbfe3812a6667f04cd318f3da127a0dd46170cfbaadfcca863e0d4240ebec1cb2a5952881fe89804892d36dc5bd6484cc78db41bed868ed1b321a680a293bc29c420cffb5305d15fba05c76c2138b986f799b6a3d061658e498204c2b641f2f2ba73d633538eef6b5a01117951eedb7611742c120ff24261bea605e94d21e452ddb9ad27af08ed972b7d5e1eae010ec5d83e4505f6a2b7d9a0bb32a1fbba32a2a8c7823e736a69f516b781fb5354be4b0a67343c009a09b8f656c34ab895f9213531fdeee911d677d1cbc5e72c0fd1ad1f3b4b8bc735e14c3f75f1828ea28c90cda40e0cbdc40dec37031ff3d50305d5a8bba1d53d2f176895e53faa3067129a5c97505799967e55e4e9d87faf5920d71055009fd060ad06691b78583f63881b566d4a06b639c55796b23531ea79c6de24092c0e6fb4d3dc739f6d82ee3ee39f229de4c844aba36432d6119be0d2f02e5f72ef1d95fb2494522a7221e18e92cf22e00010ffd93b89fe60b6895a37fca91aa2fefa8debdae3147fe4f01a6adbfa0a59a5203516b2cc7de5faf821a2e72d43beafa30ac379791ad1e5da3286abecfc7a546b80191b7b892cdd01c25e95506471f5eb74568257439aea03300e80699909cc06db2fd607f3279651f7392f80bf4fc61d66f0dfed7b7db09744139d7374d3cdd18d153dede2a65f26130506acc51d5c721a7989485a145dac9565ef6d3cc938c5a51f31ccc88bb0739920ef8f0a01145f4ddccc74790a22a3099a4b57e31b3a01b4118c9e6c393c1304cc51ca1784db5633eb96ccdc88f8b732815b92c9072dbeb61a2cc1e6b2e7098d883e6174f5af7bd4f129389250926e041ba94d1ac543aab6525f151294060791fd26b668d09302c3482c78e5f3271c0150c437b4e78b1cff6f2b8660dc310965f2df14a1f2ad45cd2759433c4f3952402fefd79fff00dd309c3f09a58600223441c11693cdeeaf0a6100d38d612a759a8e01f753982803af30c7470f7bfd1ccf2c08aa0b187382d25868a9fdf729da10bb0aa0e1cd9c6e695eb2c80c6b6ce62737c3e655246edbce5b8f7ae21c473762db0969dc216a93d4db239f67dea74a1de21d50336793d1ae45e931d975bc706ea718a2ab10d66a59d9d23f76969d870ac279611246ed3aab0f79e11611b312624d78b88a9d1a49dc68d6968f7428c33f0a7a65675826422f7ac058101d2f85663de331345b3a25cf76b7c8fe0988a13278be9599b8e4708526b44a70bc31ac5c278ab739e3e6f0927b72507f34b0034e7fdf43364c466bb75b559e03d4d18c864714eb6061f83a6331b3f59dd62f39bfc2529d5cc68bb6ce63db1075105cbd7d7c4d4ab68c9e65a32092e34e76c3178382a965f49386bd4aae307128242a2ffe3022fd7dc1a824b330b9f032d55573c2f004a6905178a2479ba8a2d5b3140ed5f3e10d986265d8b4cf262295658f301b4d36281611d9c61624928da9abc51ff9a6eb481310511772fcb1c1786203d25295e4a319b9c6d65ccc966b4c5795e6e30b2b3ae8246c38b4a911d1904145de63dbd4470fac47f8ee3eeb3f58b5e665c26a316362382ccc6bf8db7699fa3334cb2ce61c746a7d3af24d8030df6759835f5890b7dd1de538cac1dfe843ad06eba2e887f08d9a49b39246fb26eff5cacc937d63c8d0136f7a8ed2af4cf473f3f0d9064f97fb4fe9938d631f7cea3c617c38771553eddd606ab80bf792f34b44111933796fe1fb8bb104223a4de9e16e17321ea7f8de3306e75a2bc79aa5e9c0ec8dde9b3dd1f2ae42a6a278410afa8fb62c16282f1e3dc1e2f8c28d4538a75b5da7645101253dd43aaa150b273f73e505d490490314606264c737bb344b616a80a4931825043a740ea4f75847e98cc99c6880d3085787903e54c63e90b60f03192234ab20cb41c70c6e82b00e0575a1bb0b0f435831c9ceb9dacd1fab8a7328eb3e28533d5bfbeace430e21758cac204631bf033752f947f78ac2bbd9423c2baf4dea22fcc65c96c332ece9abb20fed504643e82f3ba0fff213635910789a2fe1f2cedef68799fcf4a86d63ab0ccd395d6d4f393f7ee8905eb77df32d97592fb34ac86dcf20cbe5afbf9e9cff37bc34d75af046a09a1781cbf51ee2e0b0f40096d85413a30de974c4d1d16ec06c0fad00716c4e10f8dae46ef3cf27ccde74502b657d3dd26b5481d9787f5c6034083ff88807896da55fd2c951a28f15c8c9e6c86ab50c369e5ba4f6311de505c07c7b85573b5a539785820c672557cee4b58dcda948fb51c95674c23f1275b423ee5bf3a646df19bb5dfa22747857fb5c605669f334d116710bd9f1495e242bf47d6b607c1c9d9c706ee770808484ba552c978ef64daabb642a7caddf5a55facba474b8a63577ac817dc57e48ab072bc6a2cc5f5ae96edc45af41c896cecd8acfc36604db3b7fed9d2d17d429f94bd2542b194a3d3405f46c1021ecf6bb907fdfb4b53fe445d5adb18501aa772c9ba75619214384260306ab68a5ab59161b +Ciphertext = 66c03198b3422cf3fd8291080f6fb3ebd9ad863e41cdff169becde726946a342ffa0ee547a27bae28cc782d95a90b0a618f717e3beb577354bd91e00a7a57485588265ad2dd0ab946926fea7c754c42751ec7247ee84c17262c0ed092186ec57d6044f0ac9deb21da6714ec7452e441e687e138ff144ea95636286263685419afd35f002830765d810b6f60e8dee0e6879995e9272c798b067d5f99f49e460b86d67c641f48240b61a16dc7cc27b048e8b8e8e80016470ecd2fc4225e29bb127ab48dfe7e7d5a65542176dd7ad40c07ac8b92891d595bbd7afb63fb6f9e1c2aa2fc659aa101f9b6a5c346625acec86fccf17f0d45809f3b9ee81572e5627f1afeed4ba96c6d3ed7e9232358dec01a1231ae7b94ad4675239f3b456adccec439b3cdd45504c5475bbc77dfd242e5e9671d103ba71a4601a7322e0e295357f335fa8d5651d528dda66575d106308338993e615b1c5bd7e95bf3f755ff726b4ac6dd5a43ef061ac9783f8f2804c68f66486f5844969103a36278ee0d10798bf8a802d3fee3a31294bf00ee74f087749ab3325c027d42b55b197469a5312bdc5c9b316b20093154e66605941d58f4db8d46a815c06f209c1dce2363771b5a794dd8d17e93a2fa7b194c6a0b79793c06f002638e5e3052365221232cc4b30adf161cc6e7865cf02911e2ac9b0a75f000e7ef3aa4f3c7438433513da7246d421f208b179763651f18e22a793961e5976a74744696912f22915244fcfbefdc472baee0be1e591d6503f2d9511ee1eededd9f5547c95eb94de134d0c2186109935207a23b2b8420a5858d831ed78202be855cc6b98d6663c1c52e1a0022ed7ebe0eea6b107da4cf50c1c7fced9744a914a66d4604a081587ce4b7e0f96ed408b8a9a2964314b1334a123d5184889958e6467a6d16e7615e5364e09aab75994e2758345511113321a3436db79351c63a282095ec6b99b6d775a5c09ea3f3225716e39e14df260bdefb2ecfe9a65c73ab4b3712ec842e43ccdfb535e3685fa39b4912719e67bbe195e5f0fe6c3aaada2d81b669c4565921f6c183d708b50c3f7172ba841815e9351fe5fbfe2fb1fabeb7cec9bd1dcf2d6332372f1b972b5144aa7ed6c5a985132f9a54469097e2e981b9e75a7df48fa79d0736c6f8a201c7c7d0ac8ac6512a7089514bf58442dbae0529135a7f2455e0ee5716c6610bd7600b3159197bcb20ca055695a36597bf7d3b18ecd08031b4ce3a643951e231c7ad15481e32ed7a3edd2b379c8e96d3288d5b93b562972a04f1b7e0abcc5090cb8655422cf5e9dac0b49678138faec81c78f113255eaa6110e95406a7e7417a6e221a8ec7fb9d55643bd589ace2da70fcb41722e66e0efce932cd7a34218375b6dfa3df1747953b24a41f94e50b84bad4d130d5dab4194665338e06f102f46badc5dad7aa06edb01f8a31244dceebe5e2006d6ab4a31582ff46731b19071c08ad1db79ba018687f3e6afbe703b1de26c11bc8b62fd6b2fa3219fa7190379504820abc97ff6c034f7850e2c7fd335462725db6748fe45920c213c539356b691f22eb490faca24e99f0a044a9f727d0786566ad00635983692ef324bbf1f80c42b269e9d5a8df3249873c51521c81400c729ed7a5e73995928abe94d189cddf2774f1735bc2060bb2240e558699c365dee45fa68801e6a1745e03736ced1b89fc2755565e3b36c2102594d43c451122d94f4a263664bd26b2fb5bc7700319f6b08796864f92d0fdb41710910bbc13aa9cc7baac3b48a24e4f3573f315448c317c149ddb433d9ddd2a2f0cfc81c22d3dab31f184975355b41e4b36fd8f22e8efa01d61a5cbb0e4fcdd273cdf68ac73fee745faff44d44d93c5a111aefe4a5ca8e8e7c075ffdb738cc5b6466dff78ddd837c72c54941707b04d60bc126a3a2fae9540ec2e4672ae13de0d927a7bd363f8abb5a56364d6d564df90a46df9fd59e2c54d5bcb8280415257a6976d8fb24c33330af32600cd1559e0eb05d55b34be456d434bca98252fa531486ce2a24c8bdea1d57d93a550ec586920903a39ca61cbfbce79b8f3a5b1653794872b2c614458177e748f8dfd43840e5bb0d608c26389347673fd0b005f60f52c56731ee5faec6c8d0617fb53d5f2415c2e7906ea0e6d0066354b213b3e94f4dfc311e4ec6afa7e8d1c69a63cccf8326741456a5e0bd0a359b7a37c117f7892969ad7b70cba9bea0a975ada7cf67e0d7255be8d2c6e7b8788b9ff14c5d1449d6173e07b5f9d94560d46f474ab2a67056fe9f4a9fd617a617d23143adb4e7ea35f2d5cc1398fb9ed43ddcd10f28debb27eb13533110005e6c78ca4a874db68c65081ecb8bff1b64eb1e2d7b76a1da3b375dce8a92d32a6277ed847879345717b9649f27e846a701549311c7e69a96d61df616157a114bdf1663ad93a26c28e1a62ee4a7c72bccb9785639eaf1e569decf777bb0548ad9ee36788cfa1150eee3ca3c96f09052ba2300cfb7526b9424b6f7418c27a1e9bc13e4d9868e5c330c051c3885e44714bddf7cb090fbd0f36b826aacbe191dc8c35c219e19fe736198c29dc4fa1a98b5fb1805dc29ecd02f74d4510a3928448b5ee61b5991e46644850a4885bb1ee272883faf27962430de1922d0883e7e80215cf5fe7e8f3fd0e2a49bd50727af793cb7e5b40860e80a1fbb9d5b5696bdf2f741909ab5a713de47716332df6c4f78288edcd6ea130d895fdb2f29f94635bbf2061de55f1801bd6a24294aa199d78021a1ba771c651de4bc08f032fe6ad7a5caf6a6afc6de649b901f783a0ee0fea9b803beeb0f431400d0707f159d7dc29c0c334a918fa08a653137a4a8bc86066c8800e1d171f1dbddf1fab8a3eff6b5023da96f002e7e217e826fa378b15dc8a376db30228f5d6b629f331a162d63e53e5b5bd7ff9ec098b4314285908281930ff0a8aa86a6d89411e6b5bc6b9c9e931623ccca6741fd6d36311e6a8e323a37ad40b7a2797b84694e736d9c135e52d149c760e727598726378cd674b0f4df1c361de0a12a2b8232e611d789bfbea699e8e77b99f3449609caff3d6ef7233df8cfc624376c905eea46c6f77c0b01d288868a19db77e227dbb5bfea5cc3f49d219c7477f7f2b3447b0b8efe08eab8f69579d727555e547c13ec7ae13b83386f2adf634140c311b6e2759cfb9c8aca1c32bb7c002d0f46ecc526916589a29e328ded9679c2163838f071b5b85b35e5e7d99c3c45d25bb9d37d7bafb8350ad4695a6e0cb7ea7d93868c30bb54e301e21147696b7dda156226a5ef8c62121e6b2cad0c4e192116192012468eaad46bea69a140aa3cb9056dec87c911636a1e55695b9e5a27c63cd8c03f31570d4b7507d13731ea31f082b33c6db8dd6e22282f9790be41350a96abfc4dc3de78e0a698930f540dbda3fee923a463a4c4a66bf00bb2cdd6d22b62a47af96b78b1f0f0a174e4ec5b785b3820f47d3c8cc1691d4751ce4e4ab78a4551956158a36717dc35488e890d0631241906db565603205e054815aaaaf17945c3372dfc7193369871e2e88fb84c15a2b9071101e1208177fc18397e6af17b5843e1fa75392d8d3ed214975d50f2b19c24e83f010f8c394ec1edbb1cb912e61627d2760b0e630b986bba2ae113b8f3b51ba00ddc495520274a85e6f6fa7573ac4ec6e2a86a1da9199ceb007aa6f132e5ab8ab8fdca7c829f452ff17524fec475b8f485b29fc6f0d972eea4ce98e242b5d58f6ddc1b3a71256de1c584c9914a3cf1e469f0033165d934fae68a7559011dac7a4e0c72e3b398fab8f8cc2fb67963b0f9220f410e5ba13026a27288a1d49edfaa51e8f220503fb5ec476147cbea975994fffde3ddc51bb189c470078978d238f5287fb2629d23989875d74b006a4122f6a342c996d4a244e8c5e4b804a44c301ac4d6054181a07964b279e0a44c158364395a2ead40053d2f3350ea0529a57552ed835513f533ee0c4b94ef674f31851616a4fa2d0302d13cd4aabf5f96ce28219c0b5bc0e5410fe0fa387ba1009a6f2280f9e7bbe20c33be5eb411a5f6327714b3443b4152cbc54c4012473237dd98b0490fc4228ded74afc81be2a58a22e03ca987faef5310e474f4f5a183f6b7ebede5a8df8a0f94a87a41852826b29466fd761f40b416ad0f263dd34e5497867766a361af1654c3fcd6ee7e6bb3f72d64cc980f04305b63bd574f116d1aa35b4bd642cab0cde6a29139aaa163805c6c40384313d4ec6027c891023083988c1b0d2edbdd9b1afe102fbda285a6f897efff72a0d7fc19a3cb6756cfaa2371e13be3cd167cddb90d525cba7da69608b9995cef92a6424a14df6b860ef0f09830fd7189497a432347680de0f463c0aff82df8098cc4f7753f7680c8c7374d01046b05c63be73f3a1623be778fdb0bdb90d4fb4b458af2890d15f108b0927304c91c8d62cb148c35cc93797db3ef9bba1014d89859a91da0c0a971f330600d71565d30e9c9ea8c07e7f629e1a6d578da04d37e597261cae8ab7d9a952bbf71573f1bf70e064f36c032cc624e3c980e5ea46d36232d61a57fa598347b7fb6b28401e34628b051d6ca3dea190d1d3c343fcc83175f70f77a8fc5e8791b9788989df1e37cc4881648f4fc673772003079adae55c83cf02a894b98561e4a6e4416bea3df18d6f702ad5c4f40faedec6b53cfdb5b3a52d7d43b97ee23ccfa2d30c7264ec555b15f1d9e7e19cd9890a7e8e01ff21d3b8b451e50932f189a420d18e7c7e2f103332c78c84600e5e8fdedd84f055a8b39be9a52782d47c6205c0de41644b09c0931f2da269a7e58e669f3b61ebda28ab8e3f9b83ff3d2bce37864af494860b2f01b000abeb737fbeaf8f9fa6378366606dcd0fc33031b94f9a7a0e562c08ea720a671ff92520047f69b138b4e032c3828874ec4c29e49aab302089956566372b20c0216b601c3958ed9691bbd89f1df45c6613d469e3b9758a70c860fddf768b10a6bf70237a454a2c0b70dd5d02da612a91fc5731513012a4a6fbc16d01550bdfdccaeca22bba104ccf6aeb19f21d4cdd3da231af8ec5bf2a726ee9cc7c85b8ed46d2f6fa4f1b010b2561fb69690d5a9df76d729450a6e139962bdaa2bec0254c5a252b97e7ce7eab1817f454c6121130952b8c40628065dc9b77b0f953552f5aa3ff983b6a51a51dd87c2b51a18e14adb8c80e002d0b47c61cb357babbbe3ed51d371941a8f111837ecf0e45020cb941de170c4a1b5e61bb928b1b11a8d902febd2ba016771f171b8a7ae825fcc4642d95649d53675d0027822e4ff79ffd302bfab1a0ff26f3648c7ab00c10f8d95f21e40ca2b40691bd4be79bb9ccc0bf760a05be4728bbc0a64e585207d1d09393a80d5f574442d6a933966777ab05f699c4e84aabbf753059287e7261d972745906a4fd8967bfc80ae9b6ec2ee1b22a81775f4f24999987365ae2dfb6739902ed51b9a4394fdf29f216c34567102d9db301661b09b728a79e377cf4bdfcf5c83b110a2e267abf6d40947e643ae2ff0c244af168c9f33e7685474ac30611ef95f218e0dd280899a92a41e7a759d03ce3709c2a140ebd35e199f1dbb96f7351cbe1f3de8da8c49758a49b9e724ebd3220ed6f51112944f70c0d1e9178f68a2c9476a913de00abbd1f5bcffa646f926da77a9e9fbdf81cdeaf7f9b13e843afefbca81c93614f8f1675325965b5836b8a77620a5ff162e25366718d8da7781e1a7e01fe2e9e56cf958c6273473abf5c2c8c7fb209307544e1c0726d5571e521621b18b6da3064b473423536b1b76ed75b21b4ee205d7ab5f081bada63062706bd155672dccf84614210d72660095437c6bc2213d9c904a4ba1bfda14d350fa3dce7141e817a50859b1a74aa64560b2ebc67add9f945b6e85577589817078c8ae54a9fc311593d2cbdb6692b089ee6264cebcc7719753f80e30dbe48b64fcfd1037fb9ddab69a5ff9e5898bd8aa947d9ad827c26df67c6786edcacb3478a20bded1ad8c48018ae0d439bb5afad5d39bb8fbaf22d72ffd759c4fa2e94a5a89f41358ebdc4c3aea5110f1965a049fdadff9cf703eabe9628e2680fa4e70320d304ecaed13f513f27220db1916ca1500f1c2e091671fb71329dec0bd6e310c83e67af61b8ab60ee1a8d559a508d174648b1bca451ef0ab0ee2ef74f4fcfaad1cc5ea6cadb8f1bffcb1f2c05122011ebbf6abc16838e452fc47653821589da4cb5bbac10deeea3ba0e0a6241338e64cc78d7a923d018e8b5b51c4442070e5b0e6f1e8c2b83791e930899c5897a602c401c1b85827962ff56d19c06f5af033059bc7fb1bd29b65f66aa5b4397834e846935e523b16438a42c1f990ebe4f83182163ca5fc60a4c6d77fc182e81fcda943a962e9e7f00f6399728b48bbe38d8178fae3582c8d9998e49df5f28e32d541636df3cdc8ac00df45db12da2e5e76f366c1ea8667ba5f3542d21f58ead7c55d06a4b35251b8f77dd34d3de262947379107a06d2f4891ffa0ad3a3e5bb2bbbb978af4953310d4cbe5525ab344ebb98ed24d003600de8f3af36ff3d0a7efeada963845d573685bec2221403b994f97b1e714fd7dccc300b62c2a516e9c6780983062eddde0178e93fcbb2ed4f06f60767356a11d22ca37078fda1ddb3cb907d1020f62ba85d09044574ba28aa3df36988eb8a41e4305e5b0687abe43a90e4f68f0374b6b05049aff5b065d7688cbbfb0e96ab03df38903bfa1c269f43a114085eb4596aec87ced88701b42f0b7426389727308bf10aee9d8f15ebdc411ce1e764a290a12faa2d7c1126dc7b5076f219b826ac8d380b69af7f95d69fc3929a97f5c7da1db6270e9ee1f2a5f7fa3a1b6bfcca00463655121f681d3a627d03efdf0b5fd045fb153bc4488a9a8b7264373c710ebfdb1c267fdca37723b21d5c3eaef48e784bd76e27c133cbc24d114f610c79f2a1f2c30d87ddba395887030b65097ca5566eb0361e70615b46d4b86c2759f1cc2efa3915b4cebdf51a745fb3c6cec69a1fda2ec5e884dce228e30af362815d2d8b59a14f89606bc77439042109369a9648db7d71024ed6df06c8ebd22e8623f48feea77f48b5e88827fafa84b0564151a5997b7f29c4d3d18068e34f2690a293d54003d0ea8f3bab9387ca72212cedb5f4602ad047dbffae2ab3a4cd2865bf896cd96f78b90e4017eb7e3c7092320c0a37f81dd65a5c4817a4e7053e6d2bcb23b11e09f681587f3a9361e974ad54b88c72c296629b1ab754d25be15e87c414cff975fafb3d7cb68167b21f1889685a48966705222b525fa47143b00041df94817c275d93c2550fdd82471cb3cc1b5644338060b767e807bca902c180b3e535c77be2651b3962287b6d1f6403033de4e0aa3a20615ab59d290f4b167325959c1524ef216dda2ffce86b50cb6b56b62a20a043d9d78c704479c22340151df5a1907670f8d4f8c90d93f7b5d94d04a4d383914867aa3c0e5ac85fc299a4d2801a3f80f4b0f046fb62c1c8c539a83b21c7549df0afe200537b52c80ebdbad8a438e430cf876cbbfee9ceb1bc5270577c27d53b40ac153cab377a565b1a9fbdee8bf8e94839c0fc04f7f664383bc90d56ccd1cc01b465c250b158b5e6f321c20db245602d10aab80c553d52f17282b095b5e2234c6c689a84b096112100359816cef7e92029fdfc048058f847cd2f2369ceec9fd171a0487bd7acfed6b0319832df6d59affbfd460ce8d12e4171da0f094e872a2888fe74925c5ef0621c4edad337f7006086748913b24d4d48ce36e662fefbe672b6d476456b1fbac6d80030ab93da93acb4a7e10f955547e7e20a0abcdbf909f05a2ee2e0b7485fa16be652b9d9fbfbf01f082488a81022bdb69af9e6fbe753e9eb92a1762afbb4df49f83ffc0cf03db563aa96fc5ba1af6d4d7eede6067749e8ecec79b63e09742e29e99e1c960dfb0688b0222c49ed919379ac66e3fa1c72645122d1664721e78fefdd1224c0b886f6e214e37d268ca9acab76ab3adc9f5549e5dcdbb3d31ac34ac472894d004eed71f88ca2377fcfa48d3ae43805dc612891dadd06c263ed8617194f890bcbb964f010d277ddce1f6682e661577ecd51a4d5421f00935a5b24fef0ea1809fa5c4fe9cf8c453046f61136ec8872915d2462157d73a205d56d77bb83cf16b88cadf6430c0e5397fae1f91a6a11b177bf04b065a2e55df81d5c086ec8dc8a0a660eed37d41fe4d8b3e3f22238e2a63b6e4feee1fe9a140ed37b2be4193f75c2d038aac7f6b7dad2a3b37e5b9b660615ec1db77a9b7ab416f43e66c872b71cb67c9245c757dc87723ab3b9544fdd8a16c9486e8ec3c4a44cefd98535d6e5683426c1cc8c888b8e0c2e7528bd7eb89b80d9e00969efd2f0a0fb09845426edf0d1d9a0809648e7e46ea0a8c9988bf9df475be12a72c7326c1f2bf01afafb190cf6f649133c7dc14ecf9b8c971135bd303c8894bac637e08257d45e1b68edf550d896c41682c002396e8f1eb7c1e2f4e0ed9b8b7010fc7847e6fb1c5907c17b2d2b7cd24c96f47406bd04cfcb2099d82dc2902d6f91e2f8f3a05bc62019af536309e7847fc06c10dbf7272a1509079fd16bb16a85ae2e078f97f9ce66bba66d6329c7ee70f9688f6d91aa38b25c7f4884658a72ad8cbf96d7d7a9652673273ee1b3d4d17780dfe9ca865416e318bdcbe9efd8e071fcb15ceb0743df5af4f7d598b31e38677e65af61c1109fdbb11fb11e3952e6c3ae8abc3f894ccdf205ae55dafce1dd05dca6b899877f57d712223dde4e7fdec7e0ed4f0a29ad359e318eb36ddb42fb205adca400f5b2615947c4f0ede95788093a1152d88acbbbb272750823151e245354e658452a95f21fef05bbfd98a10c1c975ad1a08c59fa3efa9fc73588407a83d0b26a53f1b4115f83780bc70ee2619d7374ca45b9e200055df1b93977e17aca89a009110a6e74caec7f86114f91975bc6e8bcdc7267ed2920cf12cd7137840628e1b8a0ea181dfef18dc5f74e752f842ea91bdce4b420ee709bca72c4514e92bcff55902e5529d77fd95f5837c8f4fffce80c813630550a0dde24092a25f65eba90790a06f4d4c3e739aaa8194a147fb32e81c71d3e8def79251c33637661b0a621a2a6b302dea00d34a9dbe9b621c1dabd0464e85241aa6712d90b4287cb23c17bf1e4d0e6dbed372e6b49c4a843305b3b0e5cab0b0964a93ad0bbc99ee711afa7f2d0a296a375fdb3176c65a957ddd9b88e9d57df736acdeb02a71b924cc2e972f51ba68a597215678573bede9ca5b3a0a2461b2d3b9ea57a5af8c91d40779bf917ded32f14a66d96e28e1415fea1e9306654c6b84d8a64243a5271c1f11590423c718961aecf5f659b49f67efa78e02ef2524d0966ebcc446d73d49ab7ec31f0c009069d14ccd63f926169291b83a3e37610054b0b964741e2ed8771d20bfa225eac0280b4d5af0c09d3218bd497a035536f5af0816884d606f1a872b8161a266466b56e0be8b80a7bde65ac706eea8cacf1749e5e71ff9fa3e69ce878427a0728d44e666eff977026abfe18cf3ad156a943b917e72ad65725a9a8d60b7b5740494fa63143a7f2a94fe6d8b319be55d6fe1a988244deb798f345f30dcafdb6af9e9cee9e35733274bdf3896750897371563ed2516c4ca6c3c3c994b48cc94b67e8129d234a0e19dabe39e500214c0ed5f0e5d61b2f58d7355d147102d93b2689bc5185dd4c0a18efd11a307b887d4d0fa84fd992731b3a80dbd027dd36cd6933766c537e8e9e27d35d5187e8276b0f59fbe7b6d629d3416b782e7981d85e1e890853c3aa94a93c1667a55044ae42badefab979fe7d525c6a180307c5ee3a9c3933038028c3e1d15d1e78fbf53b6ea61ac5e02db0161719398a31570c55f73cb47ddec8f99e3e14af5adb8d5cd179f4204d080331e75bd391b19d38eb81f148c36af3e8a3ebe76209bb75c9741a89b5d0708bb0fbb0945fc6fcd6ce142d19faf0947c338dbc8d976963281866b5216421c00cbd77c0907d1e16f5e925319cf6c62f8c6e8eff0c2f831c504e7a1c0df09a54e2af708ceef39ed7d0f63d83429e9b0920c03cf85c2244f2fbac3958847113bed577dbde8992cd91be5833c75faedd5e2005d4f7b66fab8fa9305927406f863d1795dfe04028940b765bd79de6972dc7094fe1c2503a73d7b50208835216c23aab3e47094587549fdd74bb50ae21cd1354daab632fd0907e63f4c2b2d39d7fdc4fc216bfa742b4608238623cb7fa01bd851c1e7ad5ef5215173a71f363fbb7dae8092486f4a1549e32ae53b14c1343ff7fb5e2b1487d9c594a1b56e22625d275e41535534d225b7b2c9deeb0d30dba7188cf75d680d4545ed05044a0661c690a37fa14a73ba8c68357e2c948e290b5d9a4b51822824614ef2938d19ea4b650041f59f3b548f0a305b86f55e69760f37f09dfdad62651aa5fd84eef28a4431136b34a49c9bf1f2891364f86b0aae70b0414e821e3db1533b0f1db5fd232308bf118f858aab5ae974c10583f61b283a3870eb82aaa8ea3c4e2ee3c3a3d7169aa8e975ddee7f620f6c5bcf3eaaef0101b62cd54495cb8809052c9e3151690cff7c1efcc4f63b22472111a7c5d9d7d2a2be951510f60dec8c426f14700c8630f8a14dfd359addf5d9b7ae031a745ecb4e17321b385799c90f924c4780287ac187530a40b064064b9036cc46e3f87c4d23aeeed1bc22a5411c7c503594d5d1261eb9fc4da242493beee9f671485a978a32e965faf9b0e2c13f78e31e1630b72d35b4be691e90b3798e18223c1b514b39a8e1eeb7897c22fdee1e33fc76e2b2f9298ad4fd89f44163aaab23d754d98c7890e58708b81b3832aee31aeca85e76416133710aeba0e5d9f17695e607d09ae3f94be191553bc39c6df03cefb4ee05516fc02d66c9866e4eb0d89a662e309379a347159db2e070abceee226f2b8b62847ef7c51d69c5f12eb567fa13af4b4f90b3f3d9d4b6a3f68bc4dd77075081e2e99833c18b154d0d6ac360141de2a25af61d551f10a34e03e1419a37409b4c177c51a8d248157b411868eb607c34d2daaa453a0954fade5eac45d5f21f50efba8bbc9c87ff0435c70f064b42cb2d158384fe0a4d9c90030ace7723af0a6c8faecd8f97f9850e2a489a94ebcc655301e2e14711de9eb08726638a9ddb57160c5545c152a26860a17dd18172bfac138a300f60431fc49eff18c93f71400e887f878f4dd637cf5df8c1e2b12c0f87e31ba2754ac1748479eda0c4184b528554106128320dcce349939e5e6cd3434f86dc7adfee28c008a21ddf9d0dbc87ceb14cc3afbef1e06fb3f9908a4b14f5e6c43b23ba783b75a6cbfa2ebac6533661b8c1143a34e8e2a9723389c4b7087dc07701c53b169894551084aedbb423bcce2f470881fdc7240c26b3b76fd6cfeebf8eb2828b4741e5e8698b19fa0a44703cb4e4c8ed6a7e4d6063f5fab724e08a159f4f04a2f351dcfb6335ae6697dbeca25c76b55e6ec9045eaaa8706902df492b8c8cfbf68c4cc1be5d1e5a173262e38bde051656ea85ffe35d97f1b25f6a47381bc327a946f7cbf6210adfd957b2921 +AAD = 85ddde4720659e80e25168585a354eb1e021c0b5d2ee289f2314dd5aae52bdf1fd44755bb56a6e659111a1d4b4da73315bde01c7d2c15a4f7114aefd68c141049fac27acfdca24e65c51fb1c27d307cd948e13af2963166bbc9411401d124f1ddf20f890db5611385257f52aa05c09b467e3ae886decf5744ec3749e5879f2a60017f601bbee11a66604d5f3d521d2c48cea1794f77366f29c7bd12a8aa51d34a4f3fb52809561b527016bc6badf9d136156c330e1d69d1aab98c7caa9cb46e782a898b4c66e4ee3e2445fbfacaadf9a8f73c4cbcb2a1ceb604ba5637b51337fcbe0fc366da98e805ceeb29feaf05420113b16e1005079c0e88af33f5970b3d7a8b51d0d9f5120a0795063db508171b75ed07705ac6d6bfe4ecc59243091d48865536515e036860affa880bfc91aae2fd1700de15994792aefc4a176e5d49d0f9135c7d670f3cb8798bfbe83fe73de7427e0f3e6a2df561cfa15ffe6ae80d5016096c8875b0beac8cee8fb530fb421b9a8ada4d551a528d0a0b521086f5a2db371a3bf12a2ef861f831fcb44cb2baede907a9306d3e5a3af796e0a50ba2c8dd61fb03727df5f0654d837dabee2fd90eecb7b2e8f303b0d57f97dc6a52d8281574d8457c89c6a9f5d80e0bd86c90ed39b1db4253affee614e8cf1ff05166c66e7d2a2aa2fe8a81c4741339683debe189c126e7f553a5f2dc16fc16672f74aebf94c7e3041c758fbc6d0c7f71c192cfd0fb2ec52d0a0705b05815d567f3d19f9b5d553a2adce9a79159b0e38980851bf64e97f896c028a6df8363cf1f13f4654265a7b0c0b24198efcf4418c32772bafd3980dbc689fab12e85b3ef4a491e2e5ffaa2fadaaf3deb392105a42380797d3b41ef61303a6016b269ec9a9f6e3f26070ff33cb467435ecb325dc7e18728a5c2e882e720c8f876fef10f5bffd5a925cdc9689d934272019e90e3a3bbf63a295f207faa5c014e1517c7d5c18c3ed70e92304d51944dcd3604c999d4aa8d8dbf2a4c69cbbc08635c968a20dcb80f438d43c57851c4cafec0b9568dd6c19932fd3f1294afd16f019f20e40ec87f6f5dffc7717470614b2de6e9000969e6b7e561cf91c06dd379a09c6c25c7841330dc78fc5be1d9b86581a81f55c0289531128638441fc98a1ad9472d74e2be2f874aff2fcf9c941502f59f716185a4c39289ca368c6dbf5257b5dc5e57a420792c26e602e4ecbc4f17c8787004eb88ea091d6b6ddc3c85dc110b5d1f46f6e1d872723176f4c73664ecb4219258fedce19ae22360354fa4894fe51d69434c2e58e1ec665b5cc33bb295053c591b474b6ae178c8834667bef971604279440170ebf3e739a4ff19704e5886767f81edce95a3dd93d1147995e7eb6c794b7be136658ed23cec7c374705ec0d8479dfb44cc7213076668e5fbe6a508537a9157815c6e5187b89f +Tag = 469e3ef168a64945f76d7a2013f27b68 + +Cipher = AES-256-GCM +Key = 0000000000000000000000000000000000000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = +Ciphertext = +AAD = +Tag = 530f8afbc74536b9a963b4f1c4cb738b + +Cipher = AES-256-GCM +Key = 0000000000000000000000000000000000000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 00000000000000000000000000000000 +Ciphertext = cea7403d4d606b6e074ec5d3baf39d18 +AAD = +Tag = d0d1c8a799996bf0265b98b5d48ab919 + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +AAD = +Tag = b094dac5d93471bdec1a502270e3cc6c + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 76fc6ece0f4e1768cddf8853bb2d551b + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbad +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 3a337dbf46a792c45e454913fe2ea8f2 + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a + +# local add-ons, primarily streaming ghash tests +# 128 bytes aad +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = +Ciphertext = +AAD = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +Tag = 5fea793a2d6f974d37e68e0cb8ff9492 + +# 48 bytes plaintext +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0 +AAD = +Tag = 9dd0a376b08e40eb00c35f29f9ea61a4 + +# 80 bytes plaintext +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291 +AAD = +Tag = 98885a3a22bd4742fe7b72172193b163 + +# 128 bytes plaintext +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40 +AAD = +Tag = cac45f60e31efd3b5a43b98a22ce1aa1 + +# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606 +AAD = +Tag = 566f8ef683078bfdeeffa869d751a017 + +# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c +AAD = +Tag = 8b307f6b33286d0ab026a9ed3fe1e85f + +# 80 bytes plaintext, submitted by Intel +Cipher = AES-128-GCM +Key = 843ffcf5d2b72694d19ed01d01249412 +IV = dbcca32ebf9b804617c3aa9e +Plaintext = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f +Ciphertext = 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5 +AAD = 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f +Tag = 3b629ccfbc1119b7319e1dce2cd6fd6d + +Cipher = AES-128-GCM +Key = 31323334353637383930313233343536 +IV = 31323334353637383930313233343536 +Plaintext = 48656c6c6f2c20576f726c64 +Ciphertext = cec189d0e8419b90fb16d555 +Tag = 32893832a8d609224d77c2e56a922282 +AAD = + +Cipher = AES-256-GCM +Key = 53a6f0d9b8a81818f2fd7525acd65acbaac82684cda4fd357b1ceb6146b31ee4 +IV = 05d8a92b5a510c3a3dacbbc0 +Plaintext = ac0ae17d3d0ee5935e18675c36d9e43967f6da38dddec14c7ec574ff8473e11ae5019e638232323c175b7672a7462df6709f5014bbe12a1370a1ffb570177927106f995dc8f35bd6e6228de7c16acb71e583c87477dcc7b17a908ce01543496c2cab8a14a21c43b18fab52d8a882dd1d999b4275db34c7f32bcba624d128580d7566a2da4bcfcc4136d58816c437d21e90456fc86381b946b8955f0448e83564165a629cb2edb978e5941010ee9153b054ee429b315058334ad7899aacedbc0bf423de69f57c633b56033c6531dde29258694045c46a797987471ae6af8fee8ad0c1be4149605064aaebafd1c5592e61beca9b5c7771410a276c3ae517490735ddd6af499ff705b9fa68d50650e60c19f5ae2c88dbb6d612afc7be28a5f55556a2163b6f66609f7d9ba7e97c074ea39a618727421fbfbb6453ffeefa643decf11404764515d28fce8ba66b8c85d077c47a54125a38bcb6b0adf6d248ba0a9ea129c887c66ef537c45e9fd3c17ce352e3936cf139e13a5946a7dc9dcb6423ca6a051bf560cfc572ef366940e71c81aa302cb9701f9a5206e9eacfe9835bdacb6425d058022a27fe73e5edeeba98c7a3edb761578ab2ad5a442c2dc1cb3c143c6f18dbe525fedd2a9cee0ada3b2c116465c5cca9a7e5d4374b29aa4ad8adaff8d6b0d1ac3990685240ce022faaa07241f9ff445566b9e0463350792cadcafd5fdf5c37706c0025b3c627185b356d39dcb2244b15566e6e3f8942f730fd6d855daa1456fe294f9156c4b5131e5bde7f2d938ceb6c7f5deb0f847a98b7fd11a3f5d0163eef9bbeb83cfc96dd8eedd447901ff4d3a35c0ea1f691b01385eb39fd265f756bbd77bb61b1741db0502947b4b985382a08a5916da809a8afd3fb1d78d9e16f8e37f51aba100d031d9da8613e9cd2cc621025b47150b3e76775ab23412d74334bcd79746cf601407481310a923047ac68a4e6a7f7b96bcd85bb6f24e38f03c80ad41a0a581b4246ea4715ee561cdc5384a51a6fc9ed8569ba6b12bcd95e6202ecf834dd9062ec539cc8cc4ed64ab9ff85998da0e63161e7391b14de47dfde41523b6c614618bf2fd1edd68a5de1c03c4181569b6c361d955c637abbf4efdb5dbf2f0dd2544329c44b77081a48f53231fa9d4cf6f2186427e469d0cfbcd698f7e7cf773240dd2b807a2fe699f0ceb4a2339e9cde01114b2aa5c3591a82a3a27b308e1e7f092af8ad97bbe7b28d78ecd80c0c0a28372193d66bdbadc0b58e4d5408acace53bd5e12101fcb25754f8c545340fbbd1328287044a29d18f40a24b4084febebe228b67cefd970df6d44ffdc033a50534e5977bda660c589c6e3c3a28b4c500b29ff4a1c3eaefb068784a29914ecab7868a43999833b0b37ae79afe58875a0425262e0ec7e10ee8a6bc1c97d332bc2a6195de239a166486a3c1ad8de3a026e5b1757f9a778a511024a260c9809ae3b22d78f18ac483281a796b1ccbfe7a9b9f357d12d340e20bdf2037e8bb91ef858cdf2eb9d7161a756d8c244c55524f8f5be2e4f18641bc4c2409c14816846c4655be716276d8356e516640da49e8412fcfc7ac0e084a079129b23e54952d8030e1f8ceaafcd322dfb4bd189bb5d940ac83231de0585783387d0642a245183f7a251779bdb12c63e9edbf3d0c94281140598fea9e73e951ce650c984cfb1398f8813abf8f8827af5eb64a65dfd1305bccc45086438ac439a9265790fb225c509ce3c9d39e25d2276d7f3c06d7cc28d33b2c21bb38b50dca5b10afc09da83ba12ee878e0f6054e8d3e78d731671de4f9d5a7b97298b01f37c7e78e5fcf5188554bcf5d42559d3b15153bb3cd5a0d1cc4a96d02ae8b1b115d1ff617b6ad894ce0585f46a2a5f4cc1b83065c1d7b5d2f25f3f4bf9966b4c7d7156931861d5edd199c126f1ee4ff6345023419d0a4c87f3388fcfbecbb6c1e2f4745922b88085d21d4551e4c127eb423db87a51c9f9a140f8a7415dbd70c4b0173e687a40f895404f2203e14ccd61e0e5b0d5aa3fbd1c8affb5807d787d840916ece24c56c50d3d9ed9f19d73f2c80c461b5b3c07dedcdb41402c3826a958d74be48382dc741dcf3e0eb8955397da33941fc47288147736d778914a57effbafccd4cf293e6ed1c7d19b55433bc0363e41546b3638a4c630eb35dc6a074f90185cb9daaa6eab54825a4daf76f49ad918e90e5777a826d6d5d52f32f7ceaf818f87251ab4d1b5406ae94e41cc97fe022b144f26335829d9c81725b3daead621a0df71313d18214ff8dc687a7ab86b8eec3070ee1ca9f62005a0cc15ca6e2f4fd893de8fd91f6210f6c96a576024678535c962a2dab06f56be377dfa74bca089adb7327abd05c3ad7646b5e9e6fc2f29916b34c8642f3c0caedb53b8f30c2a77d1757103b7ed156cdc703911366b02cde87ce7343886987f7a8c028921a7b87c5c0aca7ada34970a6d0d32eb1b177ed8e64c1fc6839b9d08acec19560bf4a815ca6187635f0cabb8bf062e8216d3b09b7abd99e956734129e16a7c4f3beb850fe2b1548729355f9015c9bba336d3e26a27b3d75d75722f7a8170d15ebf77f325c97778a5a9d7c76d3e101eeae354e54e6fa60b58cbdd900751854ede326b58fa5caca073c630f3719d6f52afe675f10d464e8b58e5fde75a4f225063ca48d76efd1b645e4bc89d98215beae765601f635a3bc8cfc08d74722f3d95ccb4cb4e3ea977d0c534a4abb866fb9a31771222cfd998231c30bd16b6844ef71038b67d72c910cca40db7260dff0b74162449a9e2cf15d7dfbfb3a685080e6c83ff4341c95819c0317502ed49af7ae688b52c9866518f74d69b4144500ab9d5a0829b9287d5fb67b78801119ddae7a76e80be8c4dbcec7866ffa7d081406e51cf617be061530b539cca7e1ef9118cc06e8eb2a01425b45947a1d2332e360acd0654bba8f1fa43ece68467690d36f6802a32f03f9ea056e57fd548dd4a3225ad5006c6c931aef1990639498dc88a23895ff1f75520a8009dbde4debc20ecc546e378eb7ed5ea3740d2244036588471d96e4751390b6b76b39816d853944cb5677b493b36de9736ba0fa404ad4b3a7d7c54d0c15072c040064b871401b25b88559d059a9519c7e2446b0d110a4aba9c12555e5f620680d1fea2359bc85cd15b5c0bfd6b3715d647514118cd60483dbc9c83e285192108f4ea6bcbee1f0935044610c68d052ccaba23258d09465d5521e2664d59358621ebbb8f28a4627362c8397f0a9852e5d8daf53a961d4ee66299e2b54d8adf5134ceedef57011f810aea76262422236c3e1a478a759584c7880fb3f32389c4bd4b637caad7b2bd6fd295aefb150754799434e99e0fd45c1cc4698ab14d1f63eeb06e53797cbdddd45e7f87e85b45a3dd0df6335c3b1addee87ba953bde29ed98042d745c1465a967ef922993798966e1c8b96ad6f68404136be0caa2264e24d8d93aa1b99da9316c7780904753d4e0b45cf282b43a0c91bc9ff83cb25cacea2ea72563b2e759b69cabbb6a50d6a0a5ba545622e5ce576cc301ba35afadbfd1e26668782e1d741feed8aae894b564a425141442fb8470b325cf7c8e1552973463bf4e67a2ad58d15417e418bb91d2df4b1310a0a70ac744bbb4245efd2ae642609079a44cbf6be19809a5ff7ad6847432368c9749cfb336ddcc0e6f52a699b910cd24671f38af5dc39268a3c87771f07d53bf220b7c2d5058cc7b0bcd492abfedf9bb295ec304107130f0e98dacaac6dab998b511f176d48daeb81db53643ad194690b6e28c5ed2927e09a1e959c494b90db401681f67bf1e23fe9ef4c903f666ef39332a91a25c63efe9bc518e9aff61842007dda72dcc0264aa47543c0a8b1f0d25749ddfbed487282241140d4c64def1831c4d75ca975fdb03258ddd013445e08bfb479a516b011fe3a12e4bfca439407c0022889e46914cd41a4d92a25eaa57a55bc7337e5fbbd11584dca34adb5643105c8171e53cf04b1412c3107e72330ebf1b52f524b4e72570cfdc0ab179991f3782d05091ea57b1a233048bf062e88939cfeefb61e8beaa90395faf61c4d974b23723a4a5cd39d70f92620f8f4f27bc99ca67bed7fb6e594913991ca3025480ad791bc94a0def36fca491a206440ec31e32bb85850c3606c875708309be63c2b4f5c477521aa08e1d059cedaafe4fbef5523b79f88b57d0c81bbdd09202095f10f13e2609e833ff41b862b2214c22e8f2b04a363b38d26bf95c07b184b9f909ad3a92122e158d3566d2204b22d4f2f3ce11a65544ccecb01a4a5ef62bc969fddcb648224a5c7bd94f8da9a7d4df393d880f537a377888874c19dad357a0564d303a5c1485c1451ea55d68779dc0c11c7c38025660684ba3f70cbbab00d15b34c0f2342207ad548eacb32ebad95292e85211a8669b586d05b0d0b9f278a35ea4d78e97fd5dafca6b72d8e1fbf3e704a60a8ec60befe2e3e4d3d37f9d33a0feb88add59f0171ddeba0b79a52feb9a1f4a7a6ee7c6927bd10968fba788a807409346a0fccd4f7daac3c8591fc689aed881829d479e8d360cdb5819d5eac718a6f860f2d9ef6a0d36ef6e10efbb37819bb7b03ab7649173447b2cd47f3433a2422b1611dff91cee0b10c6d060d4e84a9e3f4dc194514cb67f1e3985be05c845fc92b41955d0f61aeba6268789998bbf341a8b37af48f07b13a676a11d27330529cabcd52365842be559857cbc2a63a4ea1c77fa8619040e79705c5b51f473e13b73fc09c28598e070dbbb63ce884c2843ec365d4c5bebbf815ee3314dde0bab6b0a71a398e2d9ee8ba2f832863fae7eb0c18adcdd17f1dee0df29a8409acabf516c8e6dfea5a264c1c6657f774c86a14cf96eecac18a41b1650a9e652c6c9264b03aa2fd30e333a9f24cd6b0313358e3c00943a1de63ca970b7da2cb8a0fd1109cefbf12176f5dfb59457480428b194e88449bffd8b8d87d05d30f9ffe9ac3a7442b0df3418acf9165b14242489a54b6b47ea543fed5de74a00f61ab2af553b60d8d21c76c42052c72e4841bd94cf88185c39287c04d05f6336ae581cf7528a59b2874795caca79f5600ac64ad5820a91c711ae5a1c3762028242c5c8a9aae89177ec4db5785cd07402d45805a2e2e970059e4e6483074df1bcc01f57470fb66f45ab475ebb5343b727168e355a6c25d42384e39802d7b4a8c54ac94d82de12f8de13630ec8c19f008f98c505dbbfb21b363472e23d0147d1ac555f0981e2bfd07c62d097acf930094dcf239a40699421b207ac2575b7edf9b1d772ab066362820c182c2c5097a47d1dd25ca9e0dd9c3ae94e9a8f0dece74cdeeec3a17803d5e11f037820ea20364234079286a7c291f3424292b0eec3e956513cc6b078a76a3b8ab42c5fb5efdcea1d438f7ae08507275b48f9588a15be763ad094885269efa7330f6fc9d4746997c98d9f5feeb6dff2734d75afc6a11196b35bb9fd0c0af428cacef0df2c5ad4e5fb4559f0f93af2fafad6fb77f453238f409ec71a912350d7b62952e4858927f620d31569242615345265ff1cbbd7fdfaff35a45732628da663bfff3d3af3d7b537337754554458a2d1af0e16aa8ad9436096f42e243109cad32fac1adc58d714cd3d0d8483c783006991f3da263ef5ae1ff2ea06584e45849d64a07170675c29f0b2abcf1eedbb63b6f5d9dba600996c7d5edce9ac69448d05c0704fb9f84e831b60c376b8a5d33ea22030e2dd3dd421d8e0a810a77c085a3861fcba214a8baf592d624d673fb34f906581d923d80b06186db8ce5fbef2bb750166f7556adfe93d4951a825d55b0bf92c9f25776df784f6aec808ae221cc98d05ce988fe6a13ff96083dba15500e149409b54345274e3633fa8f6685d6fed40c20a5c5705f8b37099a5949846ca15def5a6a427eb4eec72747f116366adcb9b74d3de0b125bdee23ca98ee6312f41fa3d9bba43a8d343552c969c41f766ab4341a42ec4cd6f4d1d4c4b1f16979e5389fea36a150580418d95520506fe0cb1a1d861e09d21c57d88c46e10a3c5ad1aedc8f2743f5c06f10d6da9b2bb3ec783c6f5788ce9400795022cdcec197f9dd3ee4cd26531e7f057b6d9418a0c52ecdb35a24a2a079b3d396017feca8b31aa55e3d5ef79c9ea9ccc7e3d0b47f28f273276666fa1763b3a452672fedc94557d984c3353344a8bc9fc833dee685e33d63540d0801d8068cf66cc48ddcb0d42cec881eae36fc2614f96ad67fceb5c98ec33fbade0e3049178d503c13c2d5d71f32f4582d1cb0f47a2ace578b903796768a906998bed2995798251d7eb92faacc19255bf12c0024a94971c185841113faa288beb7e58d4a98289630fb3d230f936eb1b9d9c7b94b5ac9d3a211c0b454a26e29bdffb522548a65e8dde3730918fdf0575245e71ba013ce08f6e698342a61a81b1355d2483e97c06462cae1cdc7787f4bcee4396a08dac9c14981f2a8f4614a31b019c83782d5d8370acf9db467d9d95e8efbe44274fefde5860c2333cf81593a2ada9f5bb6c2362ba97fd7c3e5bc836c327c66b57c0f023efc0c0ff6feae0e625df2f4e21057060170c844c86412700d7d337b1f7835a0dafee5206cbd76104c5a36623c7783213f8dd457b5e69a86b74030a27b3c30074242b1d97e65a233885a681ec5a8532bce9dca1998dc32c6b40dd997b99a6ed6288e0b9b09447e356bc5345b2133571e65d47db2c736a391970879103d4137cab6c0724b8e67064167cd5521f32135fb6ca43c1e118adcded8227c9dbfdc18cdce154108eba5d8c60e5362e8fffc5c9ae6ac2572188617e4ce0f432e2476c74a4227af64b58e0ebafaf0b1ce01723ecd36a2a4167b7991e28b6a9e81992fcaf7b4b906d0361add02104db83914f28baea26b50561faa46293ba5247e8263ac0347509c36405747866d2fa2beef44f366108f6a4047e282a477c28654511075ddfaad9b9844e18e67320a831e647d923b2720d65ddd9ece165c222231d3c3e7f0001d15e3c690e9831ceb369a8edf183133814bfd20dd25d50973bda58ad03c4cbda8008556fc653ef401ff76ee858c1f79a0b09b4232768e72dd06e42078923d5647cb310bb644feb24d6b7e9d1167c3676cd96f79965a066aca314089db60bdc40c2be4b69c569ec76b3bb74a43fe731bc869c9222ab5404304a513d4f7d2ec5af278f7c3d664fcde579bba7bd472bdc00a1eb4c46ff69fb7e45e5712919e8656a8887afa28cadd66461fc57f53d574c92105818a89f210d7e8aee6de2e78228b2cb03b850a6e77627f70f51bb919bddf61837a978dd4cec2db138c657214ac07b67134bd53b071e2bffa3608a0b0bac88b0ddcfc1ba4dea17191c9ad76ab8de72118893256a7e13e15a3bf98bb5757a78c58328cc4b380f3786f22c6be81884d213ec3cc2784583a47a4003a59ebea08bd06e290a892c937448e664dac672942b068b839593c442f6e1d22875e01859cd24c17d108696a3196ea4794ddfdf25721d3dd3e754d1ea884e5086479819452991403a39014297fcc734e56f8daae4d49d5c47016fc3ead550783df895542229ff3b034b5b722ae2a2b04ba70e42c174e9ddb89ffa60024aa16f297ac9383b2ccad53de4bbe4ea2fa3fe3d059d16b4b4fe9959ba3c4e58922e7fa2673f50be5b636ee7c79b445471ddf5b851ec3ac505980bb184c8fe44c7776ae9aab4e66ce31fe1bc00efced390a82f96b4866e31ba3ff832a25b1e1d00ec44bf525ae523b7102ba60c1d3a2e2bed004524afc90a064b325a258eb36315b1496c748f5407e922914787acb8b47bdc495e521518e0637eac4b1b4fe1adede145181ec7ef038d48c473d6f296b349d7cf874d329c71f272883eb7e77ff303957e159fd417d5055d82687448950dd149e1074a1785518ebaf7ac167e07f1f559893a20d133b59aa294efebdae1e19a30ec9a3e257203eb9a854096395825ef4d1e4ecf1f8daeadfa049ea6c435c50d67fd21c6f6b11a8be46502f0dda1715f5349df5330454316498660b7996432e679c73f1af33e529ac669496bde538890cc093122842e3e2e4bff937708dd4b1b1d3fc066a63824266461e4af9245032d690aac0ea5636c29606473820ee57b112e2bd68c0ce1936b7e76a7873cad678b26b560d7bb10a7dcad3f69bbf226faf2f572c105741a121fa1c55ff30b2d0b7339ed9aa4c9a3671e6e4b572800afcbc8764b16f0a61c4c1ff24c3b64992cd84f39d1a4d5532a7dbd9f7bc847258a33c509a945e53236cbc46b61fc6fad662c523eef0c1eaa4bc0a49610c8d09659e7bdfa858d2494dc3da0a54fcce229951d366fd17f4120f27ac77e5e6b777693641a853eacec09cc4dc08ff6ba22295acec61c5e6215eaf2a3a012461eaade8faa9cba630c5ce2bee6f1a4676d54b4a38b7b5cfb6c98106a4882ed88153a4f0bad3e0f3d04dc1ae5318e3b8f4ab1d122a548eed47f70edad1a164a9c5c3eb10fdecb24b0b68005b2e958980481834c4f673478d3f47d07836d3c1c513dd920042381f70f1a68671acee2fdd453a7552eba497af27127999a13a33104f0086390e01635d1a0b79d92dd43211c74047804e82d9ab26f97ee88e664871dab52a2a79443e39f06a6e8ac9d5e986252529b389d9ed0b2f55fb16ca65f6e90cc9a149065f499630f973996c1e2b6c53f2ab391b7d78cc6926b1684d066a3a74b86b3b633baaf3730acd28deaf18fb926e1ec9c1f8a2345103cc4cbec05345db57c5adcf062412f289607f5fa41194f69bc2f426a30c7a6f8d1027ee8dc96c9957e90fbd9b16475b82dfd8698195159bd7b4860004beb1fa85e6843eca1acbbb0b8c7ec0b865ed108e297a2d5f915304167e18d01e51497e6e3ea76ae99bcb849f7595fa74c2a6263e2bef65f1063bce05483980ed51eac5289307117f17e99d761337e9b1fb625a1b900e6179f3b02de57a0b5f52352298c8a2d2c816182ec169d2b9c0490097ad98e2edc99c6df683a4b5b6eb73ccee0aaf07e8cf8f2f632381ac407c5c578bc1c5a8d0915dc231b01b92dbd25c2bfd412995780582793736572f1e23ef690bfe6872c2572285cd737a4be91f4dcafef09232de77b315d73f5beb23d03625e031d2438081222b063c343f52565ae314ac47a4fe518b45d0c12f2ceabc5e05c20f607b97035afbe0e29249e47961d9cf9b385c065966b0c7ea91cfa9ed1b55a58b9aaa9de080ca05c6405fdf15bcef74177226eb225a47d532bcbc82a5ffed7fd86c2609b146d86f566d0b84f638d46d6eb696bfbbc62c4fc981a94c1d6ccb9f3f7ed7976ea7e8ff1d2a2d79986fb27f1401f25d5a83f64844fa9e839fc8855007b417b261d325b6e7cb124b27ede8ad18d2b6da8bfc4d4f50c3960d5a1c82e4557b16d05471602d2a31462e4bac9535c9a57389ae0613a674815c2ec10c19f529c9274896dfe49ab06889da517d482145ed8f57ba4b7c0434ce24090ef2459682a4f6342ecc382b4cd3409c3415bcb7f1bbaadfb7ec308eea8b6cb2912469b707c99a55c1754db0650616754735b85a41433a30b28e3946754f90caeb03c7579fc9982e6ec5501d6f23e0f2b6392acc435907d79ea11eb6955723a81c4f02bfc78e2eeb1d0408f8f06b4d2f6d20d90f7698c4e58bcfa993884424f8fcb602ef35d23737fb6aff220927e28c19043ae708fd9755256a8a1660d9c5827bab1b836a10aa23aea9c92fa3b25428b3791c5d25f3f1b63befd5480ac4192c966350edceea8938ecc608e0f063d16d427049ad62625f5177470e7a0d811e8d4273aea8f7377d51db07fc34d9f18497a0c2b5c0bc5e8778e06bf7460f0487eed54d661d74346eeada9090957159b86f8b68183e33d0c3fc134d87e068badd8789d4c7adb829fe08e4558bada5ef3f526afb2c7b6184244af0d07aa5cb525c519ed32298bb6241d900ead0532b0b1fc77a6577963e7a44627ed326741af254ab957ca0298a74323d2ee4f1bca70e20ff796491424e108e03c20f2eed7374c0aa2474a91f3ced6f46165c886a510734d606ceaa08822bfced69def33cea3662512fb42ecefee341d1b499b826ad882542374b032e907a7e6a4dddc4620a5d1002b5aee25711fd2dd6e9d4e90ee350f2889d6c1f4328e4b711fc919ef3c655311637b83b4eff39c157e0510807ec61714b843bc9eb22a0f4dac7e5cc07b8e9ed587b701d9aca2a239e76ac9a16338b74d50578956e06b1ac35ee3b822ca779922d89de7d915afd7d80831e8534b8f8a2eaed252fd862abc99aadde62d4520d9a7c3c3da86081fc36927de60e3479096a2b5025b9a789da01da969cfb0ab2f252c82db9e6663dce3888146b365080f649cf94f991312817147d8f0d1774d8d44ba4afd846060df2de1d1043659c3b94b1eff51fff84e5a81a0c635aedcf677285e0d722e3335449fd0f49a41264fb963ea5bba31dae469c789047812071d8853291fd8003cc31a8968ce7acb68a6e0172ba6ee0e9dedbebeb62143047336c5a91c77085afb01fc075938b306d7e36383ecdfda55b9b5dfdab53aa34000289c398f617a146c4a06404737600484d8d4ea960061ec2cb575dc485f65f275540d0ce7550da08417632b6f0f7d044f6f719ff839aa3e5c9db94d45225a1cf0bdb0c5bffa781572ad605ad37aa988240858c9493dee9f00ed281e93532d89aba5e9e59ec430cdd5edfdfc2ef65e094eeab71cc40b59c997943a0e0dbbc80f1e11834bf3b53153ba1c1f0ccf63b3c802439b2ef1430be6994300d9b2efe4b84e25bd3bf8a566d4851e7fff57cada544d722438e8980a31563ef0558fdd8db9bdd6f1a3e34f06104b680f63c1f80a08ec6ed74bca69bb1023fe63d24c7e7a14ce85db6e21173f2ddf14f233f3787a37e4b347e4d64907fc0a23c3da017c81c27df9fafd4695886d0ddec8c47982912eceef886ab5680a130bfacbf3c67bb4f0cc118274bdfed43bbc2ba56f048d6a390e48932469b30ac84fdfc2e812f32d00a85349bb22f2d8091e64282fca1b40811db756059de5d03861d6a22cfc6289097d23c26c5e3f000f9b34a0e1b28a1269d8673d09107b29ccaa1adc8939bdca312c69ae4a238f45410d8f1b27392d594ceea2a6b42899ee5c5857965b29bea1bc413da618899b1894f2adff3b3a7b05a626e50e42379f5d0e0a148ded33d815f59d1401b197a85656466eaf88ed30d1ad4a87985570291efbb3a2c6f22c0b111e65c843ca3c6179e94335f0f91d4696e1a31107948a042f55f264c32a35e719668483957c9c8e13fd01e5f751870a509f5f06ba41ad63cbd5f706f25b1e598f6c9709ee6bab627211bc38494962e930779ed4ea2a8471d309c4c4f0603238959cb13476b673489696c87ad9da5fef0d6467145a77ae0b1089c8626988278a85be3292680d9d7e4c6866f19b78595d611f15f9a5e37b3d145d5aff4a5b58a3286bd25a862904817afe8e9b9105584af15f54554ca5e7dceaa0fbd1111aae126d74f68bb6f0ce98094dc9a59a31d9526729efa171beda9ac5b7db9118aa94b9b5ad58dc20ae1c328e31269244d636139 +Ciphertext = d248b9e47c303f735b0d29f6111a742d93509ae051466688d56b587104a74fab1b259da64475fc0d2c3e28d87ca4edfeaa5715c23dc0e5281eb0c0c14e22182bb02f9f7d3c24555cd6a3ff766c774e67730a920db5f85d47dc23bbbee460f0922cd7ddba81ccbe727b4b489e79a19db2d012dad2a732273dafabc0fbded3c47dbe5b6b585570c39eb62850dc47f4aa0c29bf5fadf334041fdd4658fa6cc29a81192a53dcf47c03ddca9d03b33b06e5b3808be77925b7e7d8cf51fa939e023161d969f92430917d73f3aa10b83d5b7402410280561a27c376ce0b5151a51be2ef4eb9057eed25a0715436233615dcad1559fdbd81042544441857cdf46d72f5f50ee552cfd3bf166c530e57fd97f34e2e71bff8a90b30b4c4cc3e843b0f06e4eb2ff82675e428f5303aa9141dbeb615cf6aca5540fd7cb756fe5f9b08a4abdc6eb90b2eaef51c21eb9ae79a0e44b0755b3ed48f5e6e57f3148ce02501528dd3dd2b0bbec2650710a183e38510990002ce6498dc5ce7bf33d699dd18b66c0f8031d958b11d678674c355a635f4b5e8d863785f5dc2f99eba9ce74595493c017697344b651dcc2a0b1d5386b73abd8bb2dc77a2d92173d3688d0d704da9e44a6385af9fb3a81db68822b1eac9ab284f0155c20f6bc34af85d8518d0dfd32fdaece1379abca339a00e1326b624b3e4050be5db8dced5e6c4b88b82b6ee2a48c373d236ea3565ecc072e953ffe01b624c6ecbf534678aad9c3f8a07d7dd7232134b6b397d0c96ab5f795f9e3af65b96e7a765283d8081dab9f953113abe06e8d150bf9a8416d8932fac17b032dc346be43736dbf066ed239328803510f6f62bc8abc92f6df9a82c02cbf85de91739bc8d7805d392341be99798079419540dc952fa0d3ceca4b806ab1db3b717f0d720038343465a8bc0da8e8964e58634e8a2d6c99230af2ac7c89acd3f86a22075dc40818028f3c632b36a39c0e064e3ca2a078c617a3e73aaea56ef11114f9efaac90a3ec8f8d9b18921a80d74b09ada83efee127f41179dc6c19c7965f3e7f43e22f636534b123e9246172f9920f253d2a2652a5e8c337ff93b2d479bef5e96e972a9b9cd8af057c750bd711010d59ce065ad50fdd487b5dde616301d0ae6373b6f9efae99d8972f242dd7a6bc61caee70201869be202fd384a992478dfc133b84171f013244c5d17585934aed3b43b818926246227d255bf832ff481f5f8d074ab159a11d6d17ed0ac50f727b870db966e0373bd3b1eecbf9ed66aa66caf33ac57cffe4ac6df3cf7b0e54ac54be4f3d50f61b33557c2990c908a710c85000ef6fa62716960daf918ae3d81ee60b3813e65673bd911ce468510bd230b9c2d215afe86ec12e49e0ae87e4235baf3df237188f5e0af2e61c22a4bf77190dd5dc804b4cc330b360c3dc093ef208c37d299ea0cd2ba906084011e16ac5f4fc9646538d5b538a99546d34a4599c8529c1524fc4b394d6a9cd762855905233ed92e72c8b538372ffe2f0df7085eb074616c7e695d7de40779e384d5fdb49fe02385424ea991dc05c6ae813f76c673eb45d6105bcdcfdbf04dcdd20caa6e30efcf3537bcf72947e1ac37d1e8c600ba9238569a4b3afa590d61acceb2572da85885146a142c8f8c60afe4d53ee4d61f33c47e5a99da9a346bcfbd013754ef39a4d7f16c4c5fbfa53d7f180c16e2b64f97dcfd65349939b5fc167c7a78926f638f1893fe9a81e897beea3258a4175d14f41dc123ddd846e45a87f35154db8a5ac27c7a0fc95d3b3113cfa9e7c828f83a1f0d91ab7789c33be5f55ecbb8eb0c81bcc0fccc880011b21000e2f10773388b198ce79c5d694472d3ef6b2e55c342b29c70e4f33fe59e2e0bd3f9ef617733dd3329a0e426338d9c007bcdd382522cb96e59b223825a39b01b52809f5e8518f64b81c99022d8215b5c435d87cc1a57bd440b31a19b197b277b2072968595ccd64c135ae1b218046e27a7f2685d013ce3173efd07586dc72a28ac4792e804d44f9efd785ef005213df928560a20daa4c24ab07f081479270a0dcee3c26331c48a164e4b9d79a7c30c77ab06b00e9b72c190d35fb873bc095d5e6231a89b52a0737a99532079bcc72ee221b48f0d0d9ba9105f981beb4225f6efc1230d6da10fd2b58a65112a98e4bbbe1accd6e8589eb6d9c771bb911cccf42aa6cbc68d1976f0da7eff1e70277e8c5f83734ec1efb2b00708fef08e986bd6519a0fa4b5772e585ac8e37fd2a2af07aa382579498b3b75863fe792461492b8e71c4a1a2f4421705696a96601317cfff1632784b5d75fc2036ed3fa650354620781b9fcfd53f1927223fa045edf4abe7b2144512f3e3aee99f7ac3e46028bc2427aeb18e9cb40db57b696ea884658abc9b7bae0d8117f93074a3ef903528f8b55c7687cf9f0119a1f246cc9e993219c6384359e7e5e639bb294b264048060224ae168d7b9f1f795c07eaafcddb10b61ac2be3ab3e1fddf75c1f47559f38d24f0c773d0e8bc5fa85d7d33e3aa8d0f15583b8c1e7aab6f5d0e085b7175678bf11cfee8eb069b78220377819e3f4d28eb833d3d21efff543d5c6357fffb4a8fdd6ce399fca42e2d71c53c50f6b20bcbaa1650b57ff483837c39a37d5e978393c332b43021508b8ef27773164d69d0af3c0dfdc125cf30a7c49a7d8e5320d68a35e80cdfd62a0b7ce6a412f08c8062e35265fad5d1f226d590e9b068d09e48772711d7dbd786a38c0325b3d5665c2ff45ad0a20c174dc5739896ac727b34f11c7af299d36d30c69bbdc35770138cf891cfdd8123489fdef2dfaffa9c2548ebd60b0f0bcedff44691979b4e92b364753120364dc2e3b895095da828e8659575a85cca587ba05ca625480f977a6fe10181ab6ce005defbcd8894f8c71811909cd6b56eb7ffe327f46793a9e98bd7fe8951400276bb9c7607f8ba1e633034b73d7f0d040197c3f346394eba68c8accccefe05f59cb7ea9ab1ae2e172d8f466ee21c6531cec2c9dfeebc477a6d98195c28bccc1d5e23ae50e3a1ddd7de189e36ffe0e387df7be43427b194b16e18b42eacd517bba78edc9f56a2c7e89e6f13513718869da7c8c529bc337217a69e14e35cf97ff7db2c23700347f0a33ad25a299fc52b35f63949735ad864aa127053797541864b07168f89ffb7ba5c9a8bfbcb4248383a95f45461a7aee9c658c5679205f47144ba4a06175e746037b8cb6556f06405e0d537d0f2bcd898dd5fb987d96dbce33001a50abff5b9cb0161dbfe30f5df5a161ddd8a750b0cb33898c110415881fc81239f2e25440bca41a5bc46fbd3787e6c8fe8a463415cd9a82be368a02566da740dca8e40e686e1213d9c15de2d3556a1e1180b298ba3074b4ab93e469dd9a39ac0c8a173b04a5ad913e72e4d7b5ff520f108e1a1747c11b6b2fcfaa89b3ef7e669f8ad9620364b4f4f0f9ab274e76bdd631df033357a24723653e427324d907a9eceb3c375c43ee36cdeb046a6374be19ab04922da93d4dc07c5914df06fee97dd813f5fd501ca75e3c5ad53574837f2e51ba6a257134e8ee0f4127c59840ba8b1bb13592dcbe47aea50e453c7837e91bb12ad1c74fd0f149479bc0334c511a822145690a3a408caa32671ed05c2dd219ea360c67727c1fe6a6cd842301761e94bedc73f93de7091b8b6d2783a788313b2fa12595904bf5d1167a5ddc4ee151b1522de60b7293b72a62c4d08b396ed682b6a6262a212ddc8c70dbec1a972cedc09f593e21d843279561884f9759a593da7b17a147db7559f19d5d6f43ea98012872f974306037dc0d344c55403b35a5903f766359341bee5bccb696fc0fd1c7aa8803e4c2f9e6e23d386d3a202027c5792e355592efab9330af330392a7c91e3cacc4e645359edafd78b77829374cd4b644817322b7650696fa763a0cc7143f9ec7e2f6ab3c9ec2443b0c0b0a31e9eeafb7bb8c375232357f08256959a10a6d4bc98d6cd9314a2ce7feaa8c0eb1eeb15047f715d6ae9ebd64238d648ed6bc50617a360d8ff9a01aa0ce0e29338d34bb9612751445372ac6d74837c7d2d67729760216ee33476cce1a154086ec31d986cc5a14e86561c6929554fb280646164bb03e8e52588a1b947960a77d61c2d2499212a742e1a5b78805b5b64fed141d3c4834301b8a8bef31ce65edb539fd9469b590a6980d0d1bd29e34a09f87438059a09b1ea234d1bb29882e67599fc1e417db9d86332077cfb05fe440ad1243e26a67a0ea30e63cdee8850a543d76e810140547412fb1400ac87a10e3bc77d3918750a5cc3e7a0efbd736c7ed4139cd5855ddba47143362bf40b91fcbf27222017c1552360466483e67ed125745724cc713c713dcf7ef6ea3081d65d8d78b903382717848bee7410431e1040ec92373f75a1bf229816f55dcfffb6e6da33ed8e1e8b05f9348cdcd6938f053eb9f93e0de639e922627bf61a6688f9649bb9cdfce6236a176db8b9b53ce4b5f9eb9c0680c92128bd327aa7f04a745025faaf117a18d5664027ab0e3f5898b834e1a75cd4b4087637733416f8bac1ccd67cb4457005945676d03f76fd0453fdb9968643fec98d28da7c8cd7070a803b14a2459f073ea075fd023a896d3306fdabc54416e95907103cd2fb642e301c71cc48e8eabedaae356582761a14e0b3b0ef1de06002c2acf594c85820ae3a094e5b4680566b592221543c1dc5192d6b208e86b5aca91d4e3454564eedb3b8208169ce97e1632b864f1d9d4c4c4c0fd4bcc5206e8f6d64c7cdf212d718cb5b7c7ee21593ada3f33f5952e12bba4f46cb99044978fe75349c6ca735db35891351d7e5f02a93354bc45a9ec756453f053cb87430b3e9211807f81ad99b6fceb8ef1b2d655910e1f5fd22f2ee90e42abab230f8f39a8345eed6ad294a0d32416a253f829093ecae209bc1dbfadae04a373080f9ea8394a28ddfe1134309bb53ae571d2019ff2bd4be94f8176d90987fcebad323f0b2921b85b2610852973f383a2ff4a5fa82a77b13cfd50a33f29164a9ff409422cc4cbd772132856cbd08470b220ace957a6b8e02c8003d750539a38a8df19a5b662907b72e3098d77c2fc3ece0693b47ff19ce911a93b6adce75653d48ace6af10b8f1141437f9206658707b16794e349db3f1a02606ea167d0213ce3644f64ced64de3799b1729210fc31ba1811b0c226306f2466b230ae35e6d8fa11c8f932e27da8cb1bd311919bf9178ef08bb7a2b4ca2d2e6e9585ee9f916991cfcd4862f5de9fbbc63bee6edbdcfcec9173a252eb59fc6d6e58258ca8b2a4475acfc1e09a0c9566d23d92e9ada97de51895bfb0867c42025c8d089c65bba67f4dd84d7c5155a930329345cdf3b1d6e910e730df273e183190beb900344bbce8c3bdb13a7e4ecbe967a61d47921aa55bac2bbb24e3e03d386ddbfafb3b32235b5ed922ed6ac2c89ded1316b69079b826507d708a6cca14ce2244a67be90fb91ddcb0c97432703729bceb432bc856f5eb9d2f169800a04283b080f0e053670a21468df9414fda9f4153eaf1669a19ede7925f832280800f0063ceee34b9d3b0f8da2012525fa7927e76bda71954714d5f51405b920391eca2ad71160acef4091878b907974573b4cf1b377baca0340ab0e4ec546fcaa6130603ad633c3ef980e88d8f44ec5de743cdc6cd9e0e4cbdb97a5c076be9ada8f26bc54d711facec16a2401292cc167bb98cdd320ec9321414bd97498f6d9b54dbb45ffe4b3e3f88260657ee23e19de48a93595c8e3a289a02d76a27ceead05d591633464709aca117c26aa49b64667f2a3b6371984f813d7098fae7a6ba1841775b52314a06c80b4c994ef8100e233ab3115ba2c39b97f2d5082a145720ad0b12b8a7cb275ba848b3fae14fc0c82bf0353195c056b302e508982f73a8519cca722892482b9d9e6a58bfb4d862fa393eabe6aedeae1be5ed772ea3c94a0df1d9684a131c35246c68b32e46aaf89f3649e58b2e99bd6bb3923d3ab43cbf73b6b3d19fe3b62bef178f46c79ba85e23ee4b25bc561e8fa97f51605bc0b210b02aa28242e81dae9489076d259f17d25b93b0e8a2010584d907314e3bd55482f0fa43d37ae9535629d28d6f837360bb35ec869d2a959789dc49b9c8c515942a1e03650566b736551a5180a60279bdb0ff9c387beebeb9e59ed930b3746464a010a6f7ef1de3c7d76fc6899b1e5ed98213813ffb333d969ad72fd8537ef4e12ca7b78d35c24f44ac82da4a7116492ca2efd86ee6a4474014e72a5cfeee7f729b77cfdd1a5d10a03f3cf28f1d314fca36d31ef2ecb3cfccecbcdfd22367b0a0e04435654286ae3d4fee13f56bb7cdab40b4e1dd01f9ef857f94a67c1e237e24819949935ff3bd73b0461ee9020fd0a2db2cc6312ace97e4a8a33c295271453a12822db8d1438f22ed0d466150990dcb39ed042424eef7a1210c83224c856923e3251484a81a15cddb4d7ada8bb7968dcc8f85e39ca99ece8ce2ed7753fcee6900cc9b7b5691f2d67ef9be13f70d195bbd0047908025df01b4f4d581fd59239836578627d9d585ebe9b053d807e9d3ba25405029a148938a746636decdade02b1afb5ccbf2f0e14a27c98a1e130d9208bbf7da4bb4e572927eb348568921d4a3309a2c24f367c935c2a8e1524c3024ff350ac7da8d2849586817bc9d46a08a21aef035a6151e608ed93b1556a484e455819f9ac2fb155020738962e7255a82a0854b31fe20cdd351c10a33eb693c9be1a51a932e04d0364ced41ee1bf800d0c12ab5eb37fe52563666e52827720e856d4f24eb06e0aba446910aabbe36513f2274362fedba4c19398433029495284ccb499bb559a9cdbc94a0d1b733136969a743945a04e1d2d4e77fed21550af35f22651c7de802eab7a3942d7ec55a3a5002bde8d5cccc1d4ac4bb7f4926615fcece543fe5d9092d2c4f50d94fd9868775a072f4a5bcf2e5fd10795f7f172a3341ce33505ba68e7ebedc9c1e9165864244ed31bbe5c308dceff858cc42010ad8c281a24689cf2dee8a549b1abab9981d70a912174944b403ce664d8608b2f723150f5c12164e4caf28676e7a25c3928ca2a4dbe96355ef8f282e57888d40715df07bd8b5895549ad957e758abf868def1c1f5e260d26498616e2ac962bcaa33b879874569f198a91ce4e50fc50da77fea1df9f9ea900c834dcdd462d338efcf8e612aedebf254fac596507d175d30a90543627cfcef6852c7cda8b430e255c4d6d417de31eb5dba123e3ce9e2269867d9a94fdcd8ccac40a9451953085109f5ae0c3e04daadb4a2a47b0e176917660eb3c9f1aae0ec6b00635fa387e056623947c0621f0a12e86fac1881ed1dc1b9f523388d6b6596a152b3e732c561972879dcd3f0232ef0773a4fb195a90c3186c4688ea58967ce7f18386b80bd38e90cfd4cb899337ab27cba8db6523e979b4c449645bb2f320ccd28578bc7ec38f47225273fa61a2e5df97c4d76c556fbe2b0fd30e615f5fc82c3de7194caed9f5946c151c22b7a0c48f4a7cf78aa153414f2913c5eb95e3dbcea7ca544272cd13a1c52fa87759aeb430aab144fab418c835344605df3a044825965ca15de6ba0e59b2080f5844b2d110d71587e19acf14264cec2de5b8c77d18893215d1c1da0a940e7c2ee429a99e2633c216aecb7675a2314a09044951ca5a8eac798f8878fb5ea65f4ddccac53ee0c786e597169079fb6e8ceb37a71580b0904a97450909ca454a690821e249aebb75449e582fe1b30f1fa9f6464bdef654daa5ede6d4f223f4589ea25a25f4672cfbe974d51008bce296628556f55d26646e40b59f40e3149273760b40806ace3b5171e0b79865c6adb53513da2f24c4115de243150cec76107b48ca8da19117f00b5870e67eb8357e43c1b7b593c9875795d46ede26a109e05406b69fda988947e49ab195f22454c3c743c2ec51b91370b4df8d38653b353e51bb83215d122bcfa591009c007bbb6124bc590fed3f9c5699180b3b1424ad02f7c90a149b77d22dea5c996aba675c2a1a20e206d9c25d9446247d495a26486c0d0bfb09d0b5a1a177a09fa749dc36cee73af0116a6b779c2b827512a04ff0f60b483edbcdb33d2a18339463c498ae67ffa9da0aa3f3beb6bc99212f9e6961afde89045520b1f3f2e2761666a333d76030f443f53322f099035584a60978ef8b49f46d7d4d8c5c758ea52a04b59c1a3a1c2f9df3f3b6f5c45cf4b3547043b18c1d615a2c965c3918d090cc72946e8fd0b938e60e03464f4bc71fb719a1d173b0931930e58bf7f6d4403971d36b40f83be6b57244a7029e1d41dc908764d57a5442557218b509faeda4e9fcf31debbc54ae671ef636871233f29e0013c0e33933543f4b59df1978ec89b109c3977b0cf938b7f6166d6c93be5e87684a703c8b7b5fe1a8bfe153a179b55575ff05e599b39e32ed10d958699a1ffe07136081f0719b18c69dc74f66f211103e9c544f3c81a88ba9f66a9bc7017d9ca9e2cd97634052694a598476b99daf1cdfb6122869375ca5873d32d5c1e07d9b5b380b4f09dbe04478cfb1a13853eafacfed70c8abcd444ed095f78d07c0e8b4093be95c3aa24b2e5b6bfe3a06e9d2d9fedfcfeac4cea2490627e6da6a5cca383351952f654ce2b0ad359c0f7f4ad3f8d1d4a030a947d4a2e417bb79102729115cc8b6558c3362b1d805fb48ce4858deff97677e60375ed13e150a12ee7dcc8ccc64d9710c7f516555c1f7a1a08f0d7c6fd21f864fcf28c8f748c40494e01fc32006f977a5100577f86a484d11b82c90cfe6b4d6b1902fef486cc6f3e033904e150e67283e49a5382961dabd244412ca9657b48796e476a82443167e277d5a65c0c563a6abca77d316e5d3ab639a1ecfb1110af2d29f146508bd9874486dbb56328d6f59479e2766692821660462aa60b6bc8a710707ceeb0ea6429e5113e03c9f41ce0d69c7589deb547527673e8a9f9a9a74e9e4bbcabf2e306b35504c1da99730ae86e94cd047b2e6ea5e97e63a492430d37ec446434fb3b066adde08b17d7d903ad194a4a863d6cfe181a45c8c97b5062bf7c4e44d69c0d1a7e1f5029b805b7c21d1b5e56e697999a32557870ebaae8d87dcb5ca5eea2c5547a16b3f30ef9df8df821028c106f86e091050ff8b6ea4171e59dc2592d405073bea53f8ea62edf112dfbc7ca69809db8005783d63557d3d90d123a944be395c1dc3b5e1476dff188346327769fea65f3cf9363e88ed67335870ec8ef13eb9d9ff5317c4e24dfce9d11699e5f47b4233cc8f9d1b915e716a5730a5898ee65d30b1628b484a5e82eda95a590964a8d8bc89dd3c5cf6c4f9137b8c6ee9d6a692e0c0d1d858dd5b3c12de48badade4d01bff312c56ce3ddb34b0fdde3b0c2706fc292b9fac7e1a0dcd0b6534c968117f7de15eba84d2754e4bcb8093a5440297605598659f686075e2b1b464b6b3ec68abb13cde263b1c607545c45746338b9b207b5c381da690f653b35e363e1249551ad938b9fd7b0a944151cda07127bf9ba76958e926472f4aa1de8512ce834cfcae5414b226f23acdb1fe5cf685d2201b78167ad35fc1da282744c2a43cc49d49242f968f7e06de14455e7ef5adedc5b33184346018114e2d1fc7a5349e378da9b2af5b328c213888652aca9f1145363809eca7c1fd8e64a5cc3255418736e048a731f3053db77971f67014e6121a8e464833e5dbd02ea6caf385e43e9f378bfba657986bf852b32adb55e35a2675bfc8d70d43a902032a61f59f57dad2dd7d7963322136233200cb9a90c952074e9ba0fc0654f1b6fd6f7f0eb77c0fa6d8143213ce6e8b0c178f73e17a7c64839f9bebca2fc955ea8ae406a13b80a9045fa8d129fd859faa46fd27c48bde7b890f98ee938c0d78889f84181ae2f5711304fe554d4251bbc6437ced59d577a2a1f26da736193c3674adb13cef9f4cb4aa6585c4d6874b0309ecde300493b1642c595746f09e03977c8902f3a4a877db1153b248f295a0ca2f1e437d15fcab8fd77c5f967304efb5c4920b990674ae61b954af40be17a8559dc377c591b68067fdcaf2d27bd9a22041b981a84be3de50d5962b58f8c4a22fa05192c5ac99a0a9423284fe62a3a59f085136cec72cda2a53af106a2eb5bda28b6e02c299118cd91714c2e7d045346c78d9ed1b41c73231a21e42c298949f70122277f4134ed5c56639edbf3c3e717310e3d1f03dc5a94e64c4ce148bc5c6bde64eb80b17d5979892786a31225eb89bf9f5a582bcf65b83ff7aa361ccd9238d144f6a22a3f77dd8a01382df4ee90a2057dd310a6b0c4b81dfc92a2cc0c606d3be8b18fbe64ddfdf2004eeabea892be2f914edd1edd8e8829dc7704d71bbaaf08c41824dd0f4b34c9eedead9e10e53bfc6fc0bd37417de0c5c71cff0754d672f29c262d8e27b524427e12bc4e4705ab311d3bedcb1ddd09a3ca0c268c05c64951b7d724a9dafe4d249aaabda91d68633aaab845bf78f9a22d467c7e0c5fc70fc9a318b01d7492efea7fffd329d70692e76647ae665c62b280da0d62f870a52e4dc4cd92c9150c96aab16f8c23475e3152d4debb41b6756f000c3d8aceef18b49e295be7a71da1eeadf4eb96509d45d7cc42af4b7013d8bb445f577e8d4cff92770b8ba0e451f3e24c6d981efdb68c7f2dfafee40b8a425955796e369f0d4da3e998c1626ae0fa583334475f1fdde68ca211c3f2e9afb003f553191702e11f8b731c89ea26059ea4466f2bd0a1a5601025ca9417006bca5c9a57dfdba44c603ef9ad38922623b40feda036d84425c47fa42973e348a180a7570e1215044c375313ab08d6f521052dda415707ebb74d6c4774e039bb04cadc2799224bde1802e2ee2a018032e3a341700c0fa2aa28bf93cc479231efe7da0e9f68e572415348c08cf648117e9b6d1267fef6617f5927252c86cc087775db3e30180feb5ce7e1ac9c3761161e07a4853aa6d97e525aa88302954cf9390fde81f8e11d97a11c79e3bad261364c18890dd1f8fc71127edefe3571518a42be611a46a0426a33221aa25a0ae6514daaf96038cb59aaba898de49e3b215a4464e0af614e638c2d9b6e676ec427fc906bc516331a18121f306a5246d179e2d3d0f38ab8393f7ea5a2d24585e7cca649637b9983924a15483c167e8780f8dd7aa1154cbf731745a8d8d54a8c4f8d854371bb8172303f9ba3c8c7cfe8c378ee56bc35c6376aafe907d3294ee9a8786281b7deff78ff125761f1a31d0e8fffe04a52a7574eeb8679670ca3bfb740167a559488d4337819613d32752d8a89013622f6a8d70f3c64b84a4215f4b7bb282a2d17c36a326167e3270757b8f1d9a0137bfc5ec278e8ca35a69e49779cfc25b95a89cc18732b5b9d1986b18878c57e118506909207207ad0b4edf32fb2b35b6e70546f45d0849bd139ffff9d8ae547787e7b51403b54f110e2ac65468cd0910d80a4e321deafd46e9af19609bee1efa41b762b8ace989dd681503539e7d9948664cf7a73ffac9ce2a34b514253c4f21bbccd38057a6d68732930dcdfc9a32219b53339d100db0037a8bbd101e71f5054f3 +AAD = 7b3b9c07148fcd897f657ecfcc87e530191536b8e77f9309e8d7323888b3b21477f2ab7c885c105d9c29ac96aed23b366f9fde4177401b7038c6770c7bd2ee8b4335105cc0eab9e367f0cea90d6f1ae3fa76cd21ceb9f3500ce7fb4b2a3f9e90f900a231ec693aeced7afb6821391d1f5b1b957895777aa7a2b71d9571c00336f26d54d756392cdb74bfb67d5a621d517db20441f74d0940180baf613b09452f64224f8af7bbc864ab4a8434ff624d0c0646ee07132fd376506951899bde975df8c836ab4ed9cc084f1f6d500ad56345d2f250a0d6991b9e458c62b6023191f341c8659e8a38c878cfac12b032674503df9c9bb01c4340c709eb6dd7c74907d769a317f4dd7317843c47bdb4c5e1f07f2380d464b0c47269389cc8a43a09adba86f6aa8f44c8fe514e73b5fe8d344769c1aa20a4538ecfbf47562ca79fa497b0f02f103f75522db9ead50d56dbe86997d6085f1b5aa7a4cab9e51a1247ce4f724a14983b6bafd17369fac973c6be268e20d800de870928e100990ebb0d3bedfceda36c64be3a729b603bce677a49e8caf282c9159b6e3e1e775129bd30dc3f5c9849535d86a27474be03bb5749b4c0115e2614f8feaa7405cc69b1de479b3b57e551f876a9c8c57ab9879cc68bb2ea110b2e77e59dd6a65eaa67cc4d4b2f4d6e646b2a298d3c80fb43969275d4414734e74726145dab06124c040656c39a94846e8fd58d326f4f9eafe5b95d85254765a21993f55070fcb9e85db5d42ab6b9464ce66de3f236dd2a0a26c4e5535dbdcd6eb350209a65aee785c6647ad4103d092a8ac932470880eb314f7c98cdff34fdf35ee2d36f09bd443b5defad7a5acb9df55965421fd043def6f4771e1bb27385b30ba22c0d8972aead6b654085a7dd3b60c4004a0dae22e25100e54e0badd0cadf909799329ddff699de8066dd6c3822d80c73c52d87e6fcbdb2dbbf852e37804b1256e23e76dbe43f30be4a577bc23c7941a3d708d1e1f579e9c6eebc219c74768168f6790a41f883790e08cd1e88ad09a544eb97b3d1d5af67eea666b9c027e5c7c976921189b955a9e605f6cc9c012c1c2e197c5b02504cb9ffbcb0f3ed778d540d5194fdf5d38dba6340c93da7c5501a082689616f337d8b59c2a92c25e777515726e1d7f6cc9552693cc7c30f1294b37f97d49814250d6c1e3eb335c5d214ef3641739d508b87106eaaf367902433a148ca962ec694409acb82d7749e1c88938ad382d0ca6e6cbe8255746832fe737c3e71dae8397f260c98d4a292a126ec21935c24096d2f91ae114194af659455d8a4206197495a28474dd2809debf5f550d77ffac2b0db521559910c352f23472d7aa9f4dbbdb158f40aa36912cbd918ae4c642e76d78d57ade1075c4fe1086ddee3d554353b4693bbcef1cfa87e49890838c36156af0edf384b0413d6d7aa +Tag = 51cbcf4a2fd82f221de1bfebf86a8c24 + +# OFB tests from OpenSSL upstream. + +# OFB-AES128.Encrypt +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 000102030405060708090A0B0C0D0E0F +Operation = ENCRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 50FE67CC996D32B6DA0937E99BAFEC60 +Operation = ENCRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 7789508D16918F03F53C52DAC54ED825 + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = D9A4DADA0892239F6B8B3D7680E15674 +Operation = ENCRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 9740051E9C5FECF64344F7A82260EDCC + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = A78819583F0308E7A6BF36B1386ABF23 +Operation = ENCRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 304C6528F659C77866A510D9C1D6AE5E + +# OFB-AES128.Decrypt +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 000102030405060708090A0B0C0D0E0F +Operation = DECRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 50FE67CC996D32B6DA0937E99BAFEC60 +Operation = DECRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 7789508D16918F03F53C52DAC54ED825 + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = D9A4DADA0892239F6B8B3D7680E15674 +Operation = DECRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 9740051E9C5FECF64344F7A82260EDCC + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = A78819583F0308E7A6BF36B1386ABF23 +Operation = DECRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 304C6528F659C77866A510D9C1D6AE5E + +# OFB-AES256.Encrypt +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 000102030405060708090A0B0C0D0E0F +Operation = ENCRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = DC7E84BFDA79164B7ECD8486985D3860 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A +Operation = ENCRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = E1C656305ED1A7A6563805746FE03EDC +Operation = ENCRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 41635BE625B48AFC1666DD42A09D96E7 +Operation = ENCRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 0126141D67F37BE8538F5A8BE740E484 + + +# OFB-AES256.Decrypt +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 000102030405060708090A0B0C0D0E0F +Operation = DECRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = DC7E84BFDA79164B7ECD8486985D3860 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A +Operation = DECRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = E1C656305ED1A7A6563805746FE03EDC +Operation = DECRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 41635BE625B48AFC1666DD42A09D96E7 +Operation = DECRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 0126141D67F37BE8538F5A8BE740E484 + + +# AES-192 CBC-mode test from upstream OpenSSL. +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = 000102030405060708090A0B0C0D0E0F +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 4F021DB243BC633D7178183A9FA071E8 + +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = 4F021DB243BC633D7178183A9FA071E8 +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = B4D9ADA9AD7DEDF4E5E738763F69145A + +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = B4D9ADA9AD7DEDF4E5E738763F69145A +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 571B242012FB7AE07FA9BAAC3DF102E0 + +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = 571B242012FB7AE07FA9BAAC3DF102E0 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 08B0E27988598881D920A9E64F5615CD + + +# AES-192-ECB tests from FIPS-197 +Cipher = AES-192-ECB +Key = 000102030405060708090A0B0C0D0E0F1011121314151617 +Operation = ENCRYPT +Plaintext = 00112233445566778899AABBCCDDEEFF +Ciphertext = DDA97CA4864CDFE06EAF70A0EC0D7191 + + +# AES-192-ECB tests from NIST document SP800-38A +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = BD334F1D6E45F25FF712A214571FA5CC + +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 974104846D0AD3AD7734ECB3ECEE4EEF + +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = EF7AFD2270E2E60ADCE0BA2FACE6444E + +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 9A4B41BA738D6C72FB16691603C18E0E + +# DES ECB tests + +Cipher = DES-ECB +Key = 0000000000000000 +Plaintext = 0000000000000000 +Ciphertext = 8CA64DE9C1B123A7 + +Cipher = DES-ECB +Key = FFFFFFFFFFFFFFFF +Plaintext = FFFFFFFFFFFFFFFF +Ciphertext = 7359B2163E4EDC58 + +Cipher = DES-ECB +Key = 3000000000000000 +Plaintext = 1000000000000001 +Ciphertext = 958E6E627A05557B + +Cipher = DES-ECB +Key = 1111111111111111 +Plaintext = 1111111111111111 +Ciphertext = F40379AB9E0EC533 + +Cipher = DES-ECB +Key = 0123456789ABCDEF +Plaintext = 1111111111111111 +Ciphertext = 17668DFC7292532D + +Cipher = DES-ECB +Key = 1111111111111111 +Plaintext = 0123456789ABCDEF +Ciphertext = 8A5AE1F81AB8F2DD + +Cipher = DES-ECB +Key = FEDCBA9876543210 +Plaintext = 0123456789ABCDEF +Ciphertext = ED39D950FA74BCC4 diff --git a/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..a341aacbb5 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +2b57c8d88a60e99a7afbb713d1a16ce497e329a4 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..f8b80eeb16 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +ef97ddf0539eb9515e4597013f8b8ba47f26fc78 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..67988c2615 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +19fd026f4145a329dc04bb85e00e74234716cc40 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/make_all_legacy_aead_tests.sh b/external/boringssl/crypto/cipher/test/make_all_legacy_aead_tests.sh new file mode 100755 index 0000000000..12f8853331 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/cipher/test/make_legacy_aead_tests.go b/external/boringssl/crypto/cipher/test/make_legacy_aead_tests.go new file mode 100644 index 0000000000..40b8a015a3 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/cipher/test/rc4_md5_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_md5_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..f71b0c1b11 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_md5_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +329569a7682f7f6cbff0102a8c3502c346a38ff6 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/rc4_md5_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_md5_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..ecd58616cb --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_md5_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +26a282453f1cebb74b7adc35e18094291aeb913b \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/rc4_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..5917cc9282 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +721cef958939be2ab9dae1d470cd485a7d45f60a \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/rc4_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..3386996462 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +fd80f2ba8af7094d6ca3bf2056bdee98d8313e2f \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/tls_cbc.c b/external/boringssl/crypto/cipher/tls_cbc.c new file mode 100644 index 0000000000..fbc93fa607 --- /dev/null +++ b/external/boringssl/crypto/cipher/tls_cbc.c @@ -0,0 +1,564 @@ +/* ==================================================================== + * Copyright (c) 2012 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include + +#include "../internal.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 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); + } + + /* Ideally the next statement would be: + * + * rotate_offset = (mac_start - scan_start) % md_size; + * + * However, division is not a constant-time operation (at least on Intel + * chips). Thus we enumerate the possible values of md_size and handle each + * separately. The value of |md_size| is public information (it's determined + * by the cipher suite in the ServerHello) so our timing can vary based on + * its value. */ + + rotate_offset = mac_start - scan_start; + /* rotate_offset can be, at most, 255 (bytes of padding) + 1 (padding length) + * + md_size = 256 + 48 (since SHA-384 is the largest hash) = 304. */ + assert(rotate_offset <= 304); + + /* Below is an SMT-LIB2 verification that the Barrett reductions below are + * correct within this range: + * + * (define-fun barrett ( + * (x (_ BitVec 32)) + * (mul (_ BitVec 32)) + * (shift (_ BitVec 32)) + * (divisor (_ BitVec 32)) ) (_ BitVec 32) + * (let ((q (bvsub x (bvmul divisor (bvlshr (bvmul x mul) shift))) )) + * (ite (bvuge q divisor) + * (bvsub q divisor) + * q))) + * + * (declare-fun x () (_ BitVec 32)) + * + * (assert (or + * (let ( + * (divisor (_ bv20 32)) + * (mul (_ bv25 32)) + * (shift (_ bv9 32)) + * (limit (_ bv853 32))) + * + * (and (bvule x limit) (not (= (bvurem x divisor) + * (barrett x mul shift divisor))))) + * + * (let ( + * (divisor (_ bv48 32)) + * (mul (_ bv10 32)) + * (shift (_ bv9 32)) + * (limit (_ bv768 32))) + * + * (and (bvule x limit) (not (= (bvurem x divisor) + * (barrett x mul shift divisor))))) + * )) + * + * (check-sat) + * (get-model) + */ + + if (md_size == 16) { + rotate_offset &= 15; + } else if (md_size == 20) { + /* 1/20 is approximated as 25/512 and then Barrett reduction is used. + * Analytically, this is correct for 0 <= rotate_offset <= 853. */ + unsigned q = (rotate_offset * 25) >> 9; + rotate_offset -= q * 20; + rotate_offset -= + constant_time_select(constant_time_ge(rotate_offset, 20), 20, 0); + } else if (md_size == 32) { + rotate_offset &= 31; + } else if (md_size == 48) { + /* 1/48 is approximated as 10/512 and then Barrett reduction is used. + * Analytically, this is correct for 0 <= rotate_offset <= 768. */ + unsigned q = (rotate_offset * 10) >> 9; + rotate_offset -= q * 48; + rotate_offset -= + constant_time_select(constant_time_ge(rotate_offset, 48), 48, 0); + } else { + /* This should be impossible therefore this path doesn't run in constant + * time. */ + assert(0); + rotate_offset = rotate_offset % 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->h[0], md_out); + u32toBE(sha1->h[1], md_out); + u32toBE(sha1->h[2], md_out); + u32toBE(sha1->h[3], md_out); + u32toBE(sha1->h[4], 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/external/boringssl/crypto/cmac/CMakeLists.txt b/external/boringssl/crypto/cmac/CMakeLists.txt new file mode 100644 index 0000000000..0c3bf0d192 --- /dev/null +++ b/external/boringssl/crypto/cmac/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + cmac + + OBJECT + + cmac.c +) + +if(ENABLE_TESTS) +add_executable( + cmac_test + + cmac_test.cc + + $ +) + +target_link_libraries(cmac_test crypto) +add_dependencies(all_tests cmac_test) +endif() diff --git a/external/boringssl/crypto/cmac/cmac.c b/external/boringssl/crypto/cmac/cmac.c new file mode 100644 index 0000000000..fa4c3c49b9 --- /dev/null +++ b/external/boringssl/crypto/cmac/cmac.c @@ -0,0 +1,239 @@ +/* ==================================================================== + * Copyright (c) 2010 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include +#include +#include + + +struct cmac_ctx_st { + EVP_CIPHER_CTX cipher_ctx; + /* k1 and k2 are the CMAC subkeys. See + * https://tools.ietf.org/html/rfc4493#section-2.3 */ + uint8_t k1[AES_BLOCK_SIZE]; + uint8_t k2[AES_BLOCK_SIZE]; + /* Last (possibly partial) scratch */ + uint8_t block[AES_BLOCK_SIZE]; + /* block_used contains the number of valid bytes in |block|. */ + unsigned block_used; +}; + +static void CMAC_CTX_init(CMAC_CTX *ctx) { + EVP_CIPHER_CTX_init(&ctx->cipher_ctx); +} + +static void CMAC_CTX_cleanup(CMAC_CTX *ctx) { + EVP_CIPHER_CTX_cleanup(&ctx->cipher_ctx); + OPENSSL_cleanse(ctx->k1, sizeof(ctx->k1)); + OPENSSL_cleanse(ctx->k2, sizeof(ctx->k2)); + OPENSSL_cleanse(ctx->block, sizeof(ctx->block)); +} + +int AES_CMAC(uint8_t out[16], const uint8_t *key, size_t key_len, + const uint8_t *in, size_t in_len) { + const EVP_CIPHER *cipher; + switch (key_len) { + case 16: + cipher = EVP_aes_128_cbc(); + break; + case 32: + cipher = EVP_aes_256_cbc(); + break; + default: + return 0; + } + + size_t scratch_out_len; + CMAC_CTX ctx; + CMAC_CTX_init(&ctx); + + const int ok = CMAC_Init(&ctx, key, key_len, cipher, NULL /* engine */) && + CMAC_Update(&ctx, in, in_len) && + CMAC_Final(&ctx, out, &scratch_out_len); + + CMAC_CTX_cleanup(&ctx); + return ok; +} + +CMAC_CTX *CMAC_CTX_new(void) { + CMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx != NULL) { + CMAC_CTX_init(ctx); + } + return ctx; +} + +void CMAC_CTX_free(CMAC_CTX *ctx) { + if (ctx == NULL) { + return; + } + + CMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +/* binary_field_mul_x treats the 128 bits at |in| as an element of GF(2¹²â¸) + * with a hard-coded reduction polynomial and sets |out| as x times the + * input. + * + * See https://tools.ietf.org/html/rfc4493#section-2.3 */ +static void binary_field_mul_x(uint8_t out[16], const uint8_t in[16]) { + unsigned i; + + /* Shift |in| to left, including carry. */ + for (i = 0; i < 15; i++) { + out[i] = (in[i] << 1) | (in[i+1] >> 7); + } + + /* If MSB set fixup with R. */ + const uint8_t carry = in[0] >> 7; + out[i] = (in[i] << 1) ^ ((0 - carry) & 0x87); +} + +static const uint8_t kZeroIV[AES_BLOCK_SIZE] = {0}; + +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_CIPHER *cipher, ENGINE *engine) { + uint8_t scratch[AES_BLOCK_SIZE]; + + if (EVP_CIPHER_block_size(cipher) != AES_BLOCK_SIZE || + EVP_CIPHER_key_length(cipher) != key_len || + !EVP_EncryptInit_ex(&ctx->cipher_ctx, cipher, NULL, key, kZeroIV) || + !EVP_Cipher(&ctx->cipher_ctx, scratch, kZeroIV, AES_BLOCK_SIZE) || + /* Reset context again ready for first data. */ + !EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV)) { + return 0; + } + + binary_field_mul_x(ctx->k1, scratch); + binary_field_mul_x(ctx->k2, ctx->k1); + ctx->block_used = 0; + + return 1; +} + +int CMAC_Reset(CMAC_CTX *ctx) { + ctx->block_used = 0; + return EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV); +} + +int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len) { + uint8_t scratch[AES_BLOCK_SIZE]; + + if (ctx->block_used > 0) { + size_t todo = AES_BLOCK_SIZE - ctx->block_used; + if (in_len < todo) { + todo = in_len; + } + + memcpy(ctx->block + ctx->block_used, in, todo); + in += todo; + in_len -= todo; + ctx->block_used += todo; + + /* If |in_len| is zero then either |ctx->block_used| is less than + * |AES_BLOCK_SIZE|, in which case we can stop here, or |ctx->block_used| + * is exactly |AES_BLOCK_SIZE| but there's no more data to process. In the + * latter case we don't want to process this block now because it might be + * the last block and that block is treated specially. */ + if (in_len == 0) { + return 1; + } + + assert(ctx->block_used == AES_BLOCK_SIZE); + + if (!EVP_Cipher(&ctx->cipher_ctx, scratch, ctx->block, AES_BLOCK_SIZE)) { + return 0; + } + } + + /* Encrypt all but one of the remaining blocks. */ + while (in_len > AES_BLOCK_SIZE) { + if (!EVP_Cipher(&ctx->cipher_ctx, scratch, in, AES_BLOCK_SIZE)) { + return 0; + } + in += AES_BLOCK_SIZE; + in_len -= AES_BLOCK_SIZE; + } + + memcpy(ctx->block, in, in_len); + ctx->block_used = in_len; + + return 1; +} + +int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len) { + *out_len = AES_BLOCK_SIZE; + if (out == NULL) { + return 1; + } + + const uint8_t *mask = ctx->k1; + + if (ctx->block_used != AES_BLOCK_SIZE) { + /* If the last block is incomplete, terminate it with a single 'one' bit + * followed by zeros. */ + ctx->block[ctx->block_used] = 0x80; + memset(ctx->block + ctx->block_used + 1, 0, + AES_BLOCK_SIZE - (ctx->block_used + 1)); + + mask = ctx->k2; + } + + unsigned i; + for (i = 0; i < AES_BLOCK_SIZE; i++) { + out[i] = ctx->block[i] ^ mask[i]; + } + + return EVP_Cipher(&ctx->cipher_ctx, out, out, AES_BLOCK_SIZE); +} diff --git a/external/boringssl/crypto/cmac/cmac_test.cc b/external/boringssl/crypto/cmac/cmac_test.cc new file mode 100644 index 0000000000..2496f2a92e --- /dev/null +++ b/external/boringssl/crypto/cmac/cmac_test.cc @@ -0,0 +1,151 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include + +#include "../test/scoped_types.h" +#include "../test/test_util.h" + + +static void dump(const uint8_t *got, const uint8_t *want, size_t len) { + hexdump(stderr, "got :", got, len); + hexdump(stderr, "want:", want, len); + fflush(stderr); +} + +static int test(const char *name, const uint8_t *key, size_t key_len, + const uint8_t *msg, size_t msg_len, const uint8_t *expected) { + uint8_t out[16]; + + if (!AES_CMAC(out, key, key_len, msg, msg_len)) { + fprintf(stderr, "%s: AES_CMAC failed\n", name); + return 0; + } + + if (CRYPTO_memcmp(out, expected, sizeof(out)) != 0) { + fprintf(stderr, "%s: CMAC result differs:\n", name); + dump(out, expected, sizeof(out)); + return 0; + } + + ScopedCMAC_CTX ctx(CMAC_CTX_new()); + if (!ctx || !CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) { + fprintf(stderr, "%s: CMAC_Init failed.\n", name); + return 0; + } + + for (unsigned chunk_size = 1; chunk_size <= msg_len; chunk_size++) { + if (!CMAC_Reset(ctx.get())) { + fprintf(stderr, "%s/%u: CMAC_Reset failed.\n", name, chunk_size); + return 0; + } + + size_t done = 0; + while (done < msg_len) { + size_t todo = std::min(msg_len - done, static_cast(chunk_size)); + if (!CMAC_Update(ctx.get(), msg + done, todo)) { + fprintf(stderr, "%s/%u: CMAC_Update failed.\n", name, chunk_size); + return 0; + } + + done += todo; + } + + size_t out_len; + if (!CMAC_Final(ctx.get(), out, &out_len)) { + fprintf(stderr, "%s/%u: CMAC_Final failed.\n", name, chunk_size); + return 0; + } + + if (out_len != sizeof(out)) { + fprintf(stderr, "%s/%u: incorrect out_len: %u.\n", name, chunk_size, + static_cast(out_len)); + return 0; + } + + if (CRYPTO_memcmp(out, expected, sizeof(out)) != 0) { + fprintf(stderr, "%s/%u: CMAC result differs:\n", name, chunk_size); + dump(out, expected, sizeof(out)); + return 0; + } + } + + return 1; +} + +static int rfc_4493_test_vectors(void) { + static const uint8_t kKey[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }; + static const uint8_t kOut1[16] = { + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46, + }; + static const uint8_t kMsg2[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + }; + static const uint8_t kOut2[16] = { + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c, + }; + static const uint8_t kMsg3[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + }; + static const uint8_t kOut3[16] = { + 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27, + }; + static const uint8_t kMsg4[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }; + static const uint8_t kOut4[16] = { + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe, + }; + + if (!test("RFC 4493 #1", kKey, sizeof(kKey), NULL, 0, kOut1) || + !test("RFC 4493 #2", kKey, sizeof(kKey), kMsg2, sizeof(kMsg2), kOut2) || + !test("RFC 4493 #3", kKey, sizeof(kKey), kMsg3, sizeof(kMsg3), kOut3) || + !test("RFC 4493 #4", kKey, sizeof(kKey), kMsg4, sizeof(kMsg4), kOut4)) { + return 0; + } + + return 1; +} + +int main(int argc, char **argv) { + if (!rfc_4493_test_vectors()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/conf/CMakeLists.txt b/external/boringssl/crypto/conf/CMakeLists.txt new file mode 100644 index 0000000000..0a3c79538f --- /dev/null +++ b/external/boringssl/crypto/conf/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + conf + + OBJECT + + conf.c +) diff --git a/external/boringssl/crypto/conf/conf.c b/external/boringssl/crypto/conf/conf.c new file mode 100644 index 0000000000..e4fc428bb3 --- /dev/null +++ b/external/boringssl/crypto/conf/conf.c @@ -0,0 +1,788 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "conf_def.h" +#include "internal.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 *method) { + CONF *conf; + + if (method != NULL) { + return NULL; + } + + 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; +} + +CONF_VALUE *CONF_VALUE_new(void) { + CONF_VALUE *v = OPENSSL_malloc(sizeof(CONF_VALUE)); + if (!v) { + OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(v, 0, sizeof(CONF_VALUE)); + return v; +} + +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); + lh_CONF_VALUE_free(conf->data); + OPENSSL_free(conf); +} + +static CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) { + STACK_OF(CONF_VALUE) *sk = NULL; + int ok = 0; + CONF_VALUE *v = NULL, *old_value; + + sk = sk_CONF_VALUE_new_null(); + v = CONF_VALUE_new(); + if (sk == NULL || v == NULL) { + goto err; + } + v->section = OPENSSL_strdup(section); + if (v->section == NULL) { + goto err; + } + + 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, 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, 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; +} + +static 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 = OPENSSL_strdup(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, ERR_R_BUF_LIB); + goto err; + } + + section = OPENSSL_strdup("default"); + if (section == NULL) { + OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); + goto err; + } + + sv = NCONF_new_section(conf, section); + if (sv == NULL) { + OPENSSL_PUT_ERROR(CONF, 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, 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, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); + goto err; + } + *end = '\0'; + if (!str_copy(conf, NULL, §ion, start)) { + goto err; + } + if ((sv = get_section(conf, section)) == NULL) { + sv = NCONF_new_section(conf, section); + } + if (sv == NULL) { + OPENSSL_PUT_ERROR(CONF, 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, 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_new())) { + goto err; + } + if (psection == NULL) { + psection = section; + } + v->name = OPENSSL_strdup(pname); + if (v->name == NULL) { + OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); + goto err; + } + 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, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + } else { + tv = sv; + } + if (add_string(conf, tv, v) == 0) { + OPENSSL_PUT_ERROR(CONF, 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, ERR_R_SYS_LIB); + return 0; + } + + ret = def_load_bio(conf, in, out_error_line); + BIO_free(in); + + return ret; +} + +int NCONF_load_bio(CONF *conf, BIO *bio, long *out_error_line) { + return def_load_bio(conf, bio, out_error_line); +} + +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_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; + } +} + +int CONF_modules_load_file(CONF_MUST_BE_NULL *filename, const char *appname, + unsigned long flags) { + return 1; +} + +void CONF_modules_free(void) {} + +void OPENSSL_config(CONF_MUST_BE_NULL *config_name) {} diff --git a/external/boringssl/crypto/conf/conf_def.h b/external/boringssl/crypto/conf/conf_def.h new file mode 100644 index 0000000000..b1e6ba63ac --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/conf/internal.h b/external/boringssl/crypto/conf/internal.h new file mode 100644 index 0000000000..03d1a8f395 --- /dev/null +++ b/external/boringssl/crypto/conf/internal.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_CONF_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_CONF_INTERNAL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CONF_VALUE_new returns a freshly allocated and zeroed |CONF_VALUE|. */ +CONF_VALUE *CONF_VALUE_new(void); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_CONF_INTERNAL_H */ diff --git a/external/boringssl/crypto/constant_time_test.c b/external/boringssl/crypto/constant_time_test.c new file mode 100644 index 0000000000..bc127c1c9e --- /dev/null +++ b/external/boringssl/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 +#include +#include + + +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/external/boringssl/crypto/cpu-aarch64-linux.c b/external/boringssl/crypto/cpu-aarch64-linux.c new file mode 100644 index 0000000000..1b0f39552e --- /dev/null +++ b/external/boringssl/crypto/cpu-aarch64-linux.c @@ -0,0 +1,61 @@ +/* Copyright (c) 2016, 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 + +#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP) + +#include + +#include + +#include "internal.h" + + +extern uint32_t OPENSSL_armcap_P; + +void OPENSSL_cpuid_setup(void) { + unsigned long hwcap = getauxval(AT_HWCAP); + + /* 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) { + /* Matching OpenSSL, if NEON is missing, don't report other features + * either. */ + return; + } + + OPENSSL_armcap_P |= ARMV7_NEON; + + 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 /* OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP */ diff --git a/external/boringssl/crypto/cpu-arm-linux.c b/external/boringssl/crypto/cpu-arm-linux.c new file mode 100644 index 0000000000..73c38eccce --- /dev/null +++ b/external/boringssl/crypto/cpu-arm-linux.c @@ -0,0 +1,360 @@ +/* Copyright (c) 2016, 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 + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP) + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "internal.h" + + +#define AT_HWCAP 16 +#define AT_HWCAP2 26 + +#define HWCAP_NEON (1 << 12) + +/* See /usr/include/asm/hwcap.h on an ARM installation for the source of + * these values. */ +#define HWCAP2_AES (1 << 0) +#define HWCAP2_PMULL (1 << 1) +#define HWCAP2_SHA1 (1 << 2) +#define HWCAP2_SHA2 (1 << 3) + +/* |getauxval| is not available on Android until API level 20. Link it as a weak + * symbol and use other methods as fallback. */ +unsigned long getauxval(unsigned long type) __attribute__((weak)); + +static int open_eintr(const char *path, int flags) { + int ret; + do { + ret = open(path, flags); + } while (ret < 0 && errno == EINTR); + return ret; +} + +static ssize_t read_eintr(int fd, void *out, size_t len) { + ssize_t ret; + do { + ret = read(fd, out, len); + } while (ret < 0 && errno == EINTR); + return ret; +} + +/* read_full reads exactly |len| bytes from |fd| to |out|. On error or end of + * file, it returns zero. */ +static int read_full(int fd, void *out, size_t len) { + char *outp = out; + while (len > 0) { + ssize_t ret = read_eintr(fd, outp, len); + if (ret <= 0) { + return 0; + } + outp += ret; + len -= ret; + } + return 1; +} + +/* read_file opens |path| and reads until end-of-file. On success, it returns + * one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the + * contents. Otherwise, it returns zero. */ +static int read_file(char **out_ptr, size_t *out_len, const char *path) { + int fd = open_eintr(path, O_RDONLY); + if (fd < 0) { + return 0; + } + + static const size_t kReadSize = 1024; + int ret = 0; + size_t cap = kReadSize, len = 0; + char *buf = OPENSSL_malloc(cap); + if (buf == NULL) { + goto err; + } + + for (;;) { + if (cap - len < kReadSize) { + size_t new_cap = cap * 2; + if (new_cap < cap) { + goto err; + } + char *new_buf = OPENSSL_realloc(buf, new_cap); + if (new_buf == NULL) { + goto err; + } + buf = new_buf; + cap = new_cap; + } + + ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize); + if (bytes_read < 0) { + goto err; + } + if (bytes_read == 0) { + break; + } + len += bytes_read; + } + + *out_ptr = buf; + *out_len = len; + ret = 1; + buf = NULL; + +err: + OPENSSL_free(buf); + close(fd); + return ret; +} + +/* getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. */ +static unsigned long getauxval_proc(unsigned long type) { + int fd = open_eintr("/proc/self/auxv", O_RDONLY); + if (fd < 0) { + return 0; + } + + struct { + unsigned long tag; + unsigned long value; + } entry; + + for (;;) { + if (!read_full(fd, &entry, sizeof(entry)) || + (entry.tag == 0 && entry.value == 0)) { + break; + } + if (entry.tag == type) { + close(fd); + return entry.value; + } + } + close(fd); + return 0; +} + +typedef struct { + const char *data; + size_t len; +} STRING_PIECE; + +static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) { + size_t b_len = strlen(b); + return a->len == b_len && memcmp(a->data, b, b_len) == 0; +} + +/* STRING_PIECE_split finds the first occurence of |sep| in |in| and, if found, + * sets |*out_left| and |*out_right| to |in| split before and after it. It + * returns one if |sep| was found and zero otherwise. */ +static int STRING_PIECE_split(STRING_PIECE *out_left, STRING_PIECE *out_right, + const STRING_PIECE *in, char sep) { + const char *p = memchr(in->data, sep, in->len); + if (p == NULL) { + return 0; + } + /* |out_left| or |out_right| may alias |in|, so make a copy. */ + STRING_PIECE in_copy = *in; + out_left->data = in_copy.data; + out_left->len = p - in_copy.data; + out_right->data = in_copy.data + out_left->len + 1; + out_right->len = in_copy.len - out_left->len - 1; + return 1; +} + +/* STRING_PIECE_trim removes leading and trailing whitespace from |s|. */ +static void STRING_PIECE_trim(STRING_PIECE *s) { + while (s->len != 0 && (s->data[0] == ' ' || s->data[0] == '\t')) { + s->data++; + s->len--; + } + while (s->len != 0 && + (s->data[s->len - 1] == ' ' || s->data[s->len - 1] == '\t')) { + s->len--; + } +} + +/* extract_cpuinfo_field extracts a /proc/cpuinfo field named |field| from + * |in|. If found, it sets |*out| to the value and returns one. Otherwise, it + * returns zero. */ +static int extract_cpuinfo_field(STRING_PIECE *out, const STRING_PIECE *in, + const char *field) { + /* Process |in| one line at a time. */ + STRING_PIECE remaining = *in, line; + while (STRING_PIECE_split(&line, &remaining, &remaining, '\n')) { + STRING_PIECE key, value; + if (!STRING_PIECE_split(&key, &value, &line, ':')) { + continue; + } + STRING_PIECE_trim(&key); + if (STRING_PIECE_equals(&key, field)) { + STRING_PIECE_trim(&value); + *out = value; + return 1; + } + } + + return 0; +} + +static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field, + const char *value) { + STRING_PIECE extracted; + return extract_cpuinfo_field(&extracted, cpuinfo, field) && + STRING_PIECE_equals(&extracted, value); +} + +/* has_list_item treats |list| as a space-separated list of items and returns + * one if |item| is contained in |list| and zero otherwise. */ +static int has_list_item(const STRING_PIECE *list, const char *item) { + STRING_PIECE remaining = *list, feature; + while (STRING_PIECE_split(&feature, &remaining, &remaining, ' ')) { + if (STRING_PIECE_equals(&feature, item)) { + return 1; + } + } + return 0; +} + +static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) { + if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) { + /* This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always + * available on ARMv8. Linux omits required features, so reading the + * "Features" line does not work. (For simplicity, use strict equality. We + * assume everything running on future ARM architectures will have a + * working |getauxval|.) */ + return HWCAP_NEON; + } + + STRING_PIECE features; + if (extract_cpuinfo_field(&features, cpuinfo, "Features") && + has_list_item(&features, "neon")) { + return HWCAP_NEON; + } + return 0; +} + +static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) { + STRING_PIECE features; + if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) { + return 0; + } + + unsigned long ret = 0; + if (has_list_item(&features, "aes")) { + ret |= HWCAP2_AES; + } + if (has_list_item(&features, "pmull")) { + ret |= HWCAP2_PMULL; + } + if (has_list_item(&features, "sha1")) { + ret |= HWCAP2_SHA1; + } + if (has_list_item(&features, "sha2")) { + ret |= HWCAP2_SHA2; + } + return ret; +} + +/* has_broken_neon returns one if |in| matches a CPU known to have a broken + * NEON unit. See https://crbug.com/341598. */ +static int has_broken_neon(const STRING_PIECE *cpuinfo) { + return cpuinfo_field_equals(cpuinfo, "CPU implementer", "0x51") && + cpuinfo_field_equals(cpuinfo, "CPU architecture", "7") && + cpuinfo_field_equals(cpuinfo, "CPU variant", "0x1") && + cpuinfo_field_equals(cpuinfo, "CPU part", "0x04d") && + cpuinfo_field_equals(cpuinfo, "CPU revision", "0"); +} + +extern uint32_t OPENSSL_armcap_P; + +static int g_has_broken_neon; + +void OPENSSL_cpuid_setup(void) { + char *cpuinfo_data; + size_t cpuinfo_len; + if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) { + return; + } + STRING_PIECE cpuinfo; + cpuinfo.data = cpuinfo_data; + cpuinfo.len = cpuinfo_len; + + /* |getauxval| is not available on Android until API level 20. If it is + * unavailable, read from /proc/self/auxv as a fallback. This is unreadable + * on some versions of Android, so further fall back to /proc/cpuinfo. + * + * See + * https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2 + * and b/13679666 (Google-internal) for details. */ + unsigned long hwcap = 0; + if (getauxval != NULL) { + hwcap = getauxval(AT_HWCAP); + } + if (hwcap == 0) { + hwcap = getauxval_proc(AT_HWCAP); + } + if (hwcap == 0) { + hwcap = get_hwcap_cpuinfo(&cpuinfo); + } + + /* Clear NEON support if known broken. */ + g_has_broken_neon = has_broken_neon(&cpuinfo); + if (g_has_broken_neon) { + hwcap &= ~HWCAP_NEON; + } + + /* Matching OpenSSL, only report other features if NEON is present. */ + if (hwcap & HWCAP_NEON) { + OPENSSL_armcap_P |= ARMV7_NEON; + + /* Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to + * /proc/cpuinfo. See https://crbug.com/596156. */ + unsigned long hwcap2 = 0; + if (getauxval != NULL) { + hwcap2 = getauxval(AT_HWCAP2); + } + if (hwcap2 == 0) { + hwcap2 = get_hwcap2_cpuinfo(&cpuinfo); + } + + if (hwcap2 & HWCAP2_AES) { + OPENSSL_armcap_P |= ARMV8_AES; + } + if (hwcap2 & HWCAP2_PMULL) { + OPENSSL_armcap_P |= ARMV8_PMULL; + } + if (hwcap2 & HWCAP2_SHA1) { + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (hwcap2 & HWCAP2_SHA2) { + OPENSSL_armcap_P |= ARMV8_SHA256; + } + } + + OPENSSL_free(cpuinfo_data); +} + +int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; } + +#endif /* OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP */ diff --git a/external/boringssl/crypto/cpu-arm.c b/external/boringssl/crypto/cpu-arm.c new file mode 100644 index 0000000000..ef395eaeb9 --- /dev/null +++ b/external/boringssl/crypto/cpu-arm.c @@ -0,0 +1,38 @@ +/* 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 + +#if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \ + !defined(OPENSSL_STATIC_ARMCAP) + +#include + + +extern uint32_t OPENSSL_armcap_P; + +char CRYPTO_is_NEON_capable_at_runtime(void) { + return (OPENSSL_armcap_P & ARMV7_NEON) != 0; +} + +int CRYPTO_is_ARMv8_AES_capable(void) { + return (OPENSSL_armcap_P & ARMV8_AES) != 0; +} + +int CRYPTO_is_ARMv8_PMULL_capable(void) { + return (OPENSSL_armcap_P & ARMV8_PMULL) != 0; +} + +#endif /* (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && + !defined(OPENSSL_STATIC_ARMCAP) */ diff --git a/external/boringssl/crypto/cpu-intel.c b/external/boringssl/crypto/cpu-intel.c new file mode 100644 index 0000000000..f2e0c4cbc9 --- /dev/null +++ b/external/boringssl/crypto/cpu-intel.c @@ -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.] */ + +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif + +#include + + +#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) + +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include "internal.h" + + +/* OPENSSL_cpuid runs the cpuid instruction. |leaf| is passed in as EAX and ECX + * is set to zero. It writes EAX, EBX, ECX, and EDX to |*out_eax| through + * |*out_edx|. */ +static void OPENSSL_cpuid(uint32_t *out_eax, uint32_t *out_ebx, + uint32_t *out_ecx, uint32_t *out_edx, uint32_t leaf) { +#if defined(OPENSSL_WINDOWS) + int tmp[4]; + __cpuid(tmp, (int)leaf); + *out_eax = (uint32_t)tmp[0]; + *out_ebx = (uint32_t)tmp[1]; + *out_ecx = (uint32_t)tmp[2]; + *out_edx = (uint32_t)tmp[3]; +#elif defined(__pic__) && defined(OPENSSL_32_BIT) + /* Inline assembly may not clobber the PIC register. For 32-bit, this is EBX. + * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47602. */ + __asm__ volatile ( + "xor %%ecx, %%ecx\n" + "mov %%ebx, %%edi\n" + "cpuid\n" + "xchg %%edi, %%ebx\n" + : "=a"(*out_eax), "=D"(*out_ebx), "=c"(*out_ecx), "=d"(*out_edx) + : "a"(leaf) + ); +#else + __asm__ volatile ( + "xor %%ecx, %%ecx\n" + "cpuid\n" + : "=a"(*out_eax), "=b"(*out_ebx), "=c"(*out_ecx), "=d"(*out_edx) + : "a"(leaf) + ); +#endif +} + +/* OPENSSL_xgetbv returns the value of an Intel Extended Control Register (XCR). + * Currently only XCR0 is defined by Intel so |xcr| should always be zero. */ +static uint64_t OPENSSL_xgetbv(uint32_t xcr) { +#if defined(OPENSSL_WINDOWS) + return (uint64_t)_xgetbv(xcr); +#else + uint32_t eax, edx; + __asm__ volatile ("xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr)); + return (((uint64_t)edx) << 32) | eax; +#endif +} + +/* 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, "%" PRIu64, &v)) { + return; + } + + if (invert) { + out[0] &= ~v; + out[1] &= ~(v >> 32); + } else { + out[0] = v; + out[1] = v >> 32; + } +} + +void OPENSSL_cpuid_setup(void) { + /* Determine the vendor and maximum input value. */ + uint32_t eax, ebx, ecx, edx; + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0); + + uint32_t num_ids = eax; + + int is_intel = ebx == 0x756e6547 /* Genu */ && + edx == 0x49656e69 /* ineI */ && + ecx == 0x6c65746e /* ntel */; + int is_amd = ebx == 0x68747541 /* Auth */ && + edx == 0x69746e65 /* enti */ && + ecx == 0x444d4163 /* cAMD */; + + int has_amd_xop = 0; + if (is_amd) { + /* AMD-specific logic. + * See http://developer.amd.com/wordpress/media/2012/10/254811.pdf */ + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0x80000000); + uint32_t num_extended_ids = eax; + if (num_extended_ids >= 0x80000001) { + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0x80000001); + if (ecx & (1 << 11)) { + has_amd_xop = 1; + } + } + } + + uint32_t extended_features = 0; + if (num_ids >= 7) { + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 7); + extended_features = ebx; + } + + /* Determine the number of cores sharing an L1 data cache to adjust the + * hyper-threading bit. */ + uint32_t cores_per_cache = 0; + if (is_amd) { + /* AMD CPUs never share an L1 data cache between threads but do set the HTT + * bit on multi-core CPUs. */ + cores_per_cache = 1; + } else if (num_ids >= 4) { + /* TODO(davidben): The Intel manual says this CPUID leaf enumerates all + * caches using ECX and doesn't say which is first. Does this matter? */ + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 4); + cores_per_cache = 1 + ((eax >> 14) & 0xfff); + } + + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 1); + + /* Adjust the hyper-threading bit. */ + if (edx & (1 << 28)) { + uint32_t num_logical_cores = (ebx >> 16) & 0xff; + if (cores_per_cache == 1 || num_logical_cores <= 1) { + edx &= ~(1 << 28); + } + } + + /* Reserved bit #20 was historically repurposed to control the in-memory + * representation of RC4 state. Always set it to zero. */ + edx &= ~(1 << 20); + + /* Reserved bit #30 is repurposed to signal an Intel CPU. */ + if (is_intel) { + edx |= (1 << 30); + } else { + edx &= ~(1 << 30); + } + + /* The SDBG bit is repurposed to denote AMD XOP support. */ + if (has_amd_xop) { + ecx |= (1 << 11); + } else { + ecx &= ~(1 << 11); + } + + uint64_t xcr0 = 0; + if (ecx & (1 << 27)) { + /* XCR0 may only be queried if the OSXSAVE bit is set. */ + xcr0 = OPENSSL_xgetbv(0); + } + /* See Intel manual, section 14.3. */ + if ((xcr0 & 6) != 6) { + /* YMM registers cannot be used. */ + ecx &= ~(1 << 28); /* AVX */ + ecx &= ~(1 << 12); /* FMA */ + ecx &= ~(1 << 11); /* AMD XOP */ + extended_features &= ~(1 << 5); /* AVX2 */ + } + + OPENSSL_ia32cap_P[0] = edx; + OPENSSL_ia32cap_P[1] = ecx; + OPENSSL_ia32cap_P[2] = extended_features; + OPENSSL_ia32cap_P[3] = 0; + + const char *env1, *env2; + 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/external/boringssl/crypto/crypto.c b/external/boringssl/crypto/crypto.c new file mode 100644 index 0000000000..c9f2bc87f7 --- /dev/null +++ b/external/boringssl/crypto/crypto.c @@ -0,0 +1,158 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include "internal.h" + + +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_STATIC_ARMCAP) && \ + (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 + +#if defined(OPENSSL_STATIC_ARMCAP) + +uint32_t OPENSSL_armcap_P = +#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__) + ARMV7_NEON | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_AES) + ARMV8_AES | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_SHA1) + ARMV8_SHA1 | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_SHA256) + ARMV8_SHA256 | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_PMULL) + ARMV8_PMULL | +#endif + 0; + +#else +uint32_t OPENSSL_armcap_P = 0; +#endif + +#endif + + +#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_NO_STATIC_INITIALIZER) +#define OPENSSL_CDECL __cdecl +#else +#define OPENSSL_CDECL +#endif + +#if defined(BORINGSSL_NO_STATIC_INITIALIZER) +static CRYPTO_once_t once = CRYPTO_ONCE_INIT; +#elif defined(OPENSSL_WINDOWS) +#pragma section(".CRT$XCU", read) +static void __cdecl do_library_init(void); +__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) = + do_library_init; +#else +static void do_library_init(void) __attribute__ ((constructor)); +#endif + +/* 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. https://crbug.com/542879 */ +#if defined(BORINGSSL_NO_STATIC_INITIALIZER) + CRYPTO_once(&once, do_library_init); +#endif +} + +int CRYPTO_is_confidential_build(void) { +#if defined(BORINGSSL_CONFIDENTIAL) + return 1; +#else + return 0; +#endif +} + +int CRYPTO_has_asm(void) { +#if defined(OPENSSL_NO_ASM) + return 0; +#else + return 1; +#endif +} + +const char *SSLeay_version(int unused) { + return "BoringSSL"; +} + +unsigned long SSLeay(void) { + return OPENSSL_VERSION_NUMBER; +} + +int CRYPTO_malloc_init(void) { + return 1; +} + +void ENGINE_load_builtin_engines(void) {} + +void OPENSSL_load_builtin_modules(void) {} + +int FIPS_mode(void) { return 0; } diff --git a/external/boringssl/crypto/curve25519/CMakeLists.txt b/external/boringssl/crypto/curve25519/CMakeLists.txt new file mode 100644 index 0000000000..7260edca3d --- /dev/null +++ b/external/boringssl/crypto/curve25519/CMakeLists.txt @@ -0,0 +1,59 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "arm") + set( + CURVE25519_ARCH_SOURCES + + asm/x25519-asm-arm.S + ) +endif() + +if (${ARCH} STREQUAL "x86_64") + set( + CURVE25519_ARCH_SOURCES + + asm/x25519-asm-x86_64.S + ) +endif() + +add_library( + curve25519 + + OBJECT + + curve25519.c + spake25519.c + x25519-x86_64.c + + ${CURVE25519_ARCH_SOURCES} +) + +if(ENABLE_TESTS) +add_executable( + ed25519_test + + ed25519_test.cc + $ +) + +target_link_libraries(ed25519_test crypto) +add_dependencies(all_tests ed25519_test) + +add_executable( + x25519_test + + x25519_test.cc +) + +target_link_libraries(x25519_test crypto) +add_dependencies(all_tests x25519_test) + +add_executable( + spake25519_test + + spake25519_test.cc +) + +target_link_libraries(spake25519_test crypto) +add_dependencies(all_tests spake25519_test) +endif() diff --git a/external/boringssl/crypto/curve25519/asm/x25519-asm-arm.S b/external/boringssl/crypto/curve25519/asm/x25519-asm-arm.S new file mode 100644 index 0000000000..3af1dba947 --- /dev/null +++ b/external/boringssl/crypto/curve25519/asm/x25519-asm-arm.S @@ -0,0 +1,2124 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This file is taken from crypto_scalarmult/curve25519/neon2/scalarmult.s in + * SUPERCOP 20141124 (http://bench.cr.yp.to/supercop.html). That code is public + * domain licensed but the standard ISC license is included above to keep + * licensing simple. */ + +#if !defined(OPENSSL_NO_ASM) +#if defined(__arm__) + +.fpu neon +.text +.align 4 + +.global x25519_NEON +.hidden x25519_NEON +.type x25519_NEON, %function +x25519_NEON: +vpush {q4,q5,q6,q7} +mov r12,sp +sub sp,sp,#736 +and sp,sp,#0xffffffe0 +strd r4,[sp,#0] +strd r6,[sp,#8] +strd r8,[sp,#16] +strd r10,[sp,#24] +str r12,[sp,#480] +str r14,[sp,#484] +mov r0,r0 +mov r1,r1 +mov r2,r2 +add r3,sp,#32 +ldr r4,=0 +ldr r5,=254 +vmov.i32 q0,#1 +vshr.u64 q1,q0,#7 +vshr.u64 q0,q0,#8 +vmov.i32 d4,#19 +vmov.i32 d5,#38 +add r6,sp,#512 +vst1.8 {d2-d3},[r6,: 128] +add r6,sp,#528 +vst1.8 {d0-d1},[r6,: 128] +add r6,sp,#544 +vst1.8 {d4-d5},[r6,: 128] +add r6,r3,#0 +vmov.i32 q2,#0 +vst1.8 {d4-d5},[r6,: 128]! +vst1.8 {d4-d5},[r6,: 128]! +vst1.8 d4,[r6,: 64] +add r6,r3,#0 +ldr r7,=960 +sub r7,r7,#2 +neg r7,r7 +sub r7,r7,r7,LSL #7 +str r7,[r6] +add r6,sp,#704 +vld1.8 {d4-d5},[r1]! +vld1.8 {d6-d7},[r1] +vst1.8 {d4-d5},[r6,: 128]! +vst1.8 {d6-d7},[r6,: 128] +sub r1,r6,#16 +ldrb r6,[r1] +and r6,r6,#248 +strb r6,[r1] +ldrb r6,[r1,#31] +and r6,r6,#127 +orr r6,r6,#64 +strb r6,[r1,#31] +vmov.i64 q2,#0xffffffff +vshr.u64 q3,q2,#7 +vshr.u64 q2,q2,#6 +vld1.8 {d8},[r2] +vld1.8 {d10},[r2] +add r2,r2,#6 +vld1.8 {d12},[r2] +vld1.8 {d14},[r2] +add r2,r2,#6 +vld1.8 {d16},[r2] +add r2,r2,#4 +vld1.8 {d18},[r2] +vld1.8 {d20},[r2] +add r2,r2,#6 +vld1.8 {d22},[r2] +add r2,r2,#2 +vld1.8 {d24},[r2] +vld1.8 {d26},[r2] +vshr.u64 q5,q5,#26 +vshr.u64 q6,q6,#3 +vshr.u64 q7,q7,#29 +vshr.u64 q8,q8,#6 +vshr.u64 q10,q10,#25 +vshr.u64 q11,q11,#3 +vshr.u64 q12,q12,#12 +vshr.u64 q13,q13,#38 +vand q4,q4,q2 +vand q6,q6,q2 +vand q8,q8,q2 +vand q10,q10,q2 +vand q2,q12,q2 +vand q5,q5,q3 +vand q7,q7,q3 +vand q9,q9,q3 +vand q11,q11,q3 +vand q3,q13,q3 +add r2,r3,#48 +vadd.i64 q12,q4,q1 +vadd.i64 q13,q10,q1 +vshr.s64 q12,q12,#26 +vshr.s64 q13,q13,#26 +vadd.i64 q5,q5,q12 +vshl.i64 q12,q12,#26 +vadd.i64 q14,q5,q0 +vadd.i64 q11,q11,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q11,q0 +vsub.i64 q4,q4,q12 +vshr.s64 q12,q14,#25 +vsub.i64 q10,q10,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q12 +vshl.i64 q12,q12,#25 +vadd.i64 q14,q6,q1 +vadd.i64 q2,q2,q13 +vsub.i64 q5,q5,q12 +vshr.s64 q12,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q1 +vadd.i64 q7,q7,q12 +vshl.i64 q12,q12,#26 +vadd.i64 q15,q7,q0 +vsub.i64 q11,q11,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q12 +vshr.s64 q12,q15,#25 +vadd.i64 q3,q3,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q3,q0 +vadd.i64 q8,q8,q12 +vshl.i64 q12,q12,#25 +vadd.i64 q15,q8,q1 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q7,q12 +vshr.s64 q12,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q9,q9,q12 +vtrn.32 d12,d14 +vshl.i64 q12,q12,#26 +vtrn.32 d13,d15 +vadd.i64 q0,q9,q0 +vadd.i64 q4,q4,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q6,q13,#4 +vsub.i64 q7,q8,q12 +vshr.s64 q0,q0,#25 +vadd.i64 q4,q4,q6 +vadd.i64 q6,q10,q0 +vshl.i64 q0,q0,#25 +vadd.i64 q8,q6,q1 +vadd.i64 q4,q4,q13 +vshl.i64 q10,q13,#25 +vadd.i64 q1,q4,q1 +vsub.i64 q0,q9,q0 +vshr.s64 q8,q8,#26 +vsub.i64 q3,q3,q10 +vtrn.32 d14,d0 +vshr.s64 q1,q1,#26 +vtrn.32 d15,d1 +vadd.i64 q0,q11,q8 +vst1.8 d14,[r2,: 64] +vshl.i64 q7,q8,#26 +vadd.i64 q5,q5,q1 +vtrn.32 d4,d6 +vshl.i64 q1,q1,#26 +vtrn.32 d5,d7 +vsub.i64 q3,q6,q7 +add r2,r2,#16 +vsub.i64 q1,q4,q1 +vst1.8 d4,[r2,: 64] +vtrn.32 d6,d0 +vtrn.32 d7,d1 +sub r2,r2,#8 +vtrn.32 d2,d10 +vtrn.32 d3,d11 +vst1.8 d6,[r2,: 64] +sub r2,r2,#24 +vst1.8 d2,[r2,: 64] +add r2,r3,#96 +vmov.i32 q0,#0 +vmov.i64 d2,#0xff +vmov.i64 d3,#0 +vshr.u32 q1,q1,#7 +vst1.8 {d2-d3},[r2,: 128]! +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 d0,[r2,: 64] +add r2,r3,#144 +vmov.i32 q0,#0 +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 d0,[r2,: 64] +add r2,r3,#240 +vmov.i32 q0,#0 +vmov.i64 d2,#0xff +vmov.i64 d3,#0 +vshr.u32 q1,q1,#7 +vst1.8 {d2-d3},[r2,: 128]! +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 d0,[r2,: 64] +add r2,r3,#48 +add r6,r3,#192 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4},[r2,: 64] +vst1.8 {d0-d1},[r6,: 128]! +vst1.8 {d2-d3},[r6,: 128]! +vst1.8 d4,[r6,: 64] +._mainloop: +mov r2,r5,LSR #3 +and r6,r5,#7 +ldrb r2,[r1,r2] +mov r2,r2,LSR r6 +and r2,r2,#1 +str r5,[sp,#488] +eor r4,r4,r2 +str r2,[sp,#492] +neg r2,r4 +add r4,r3,#96 +add r5,r3,#192 +add r6,r3,#144 +vld1.8 {d8-d9},[r4,: 128]! +add r7,r3,#240 +vld1.8 {d10-d11},[r5,: 128]! +veor q6,q4,q5 +vld1.8 {d14-d15},[r6,: 128]! +vdup.i32 q8,r2 +vld1.8 {d18-d19},[r7,: 128]! +veor q10,q7,q9 +vld1.8 {d22-d23},[r4,: 128]! +vand q6,q6,q8 +vld1.8 {d24-d25},[r5,: 128]! +vand q10,q10,q8 +vld1.8 {d26-d27},[r6,: 128]! +veor q4,q4,q6 +vld1.8 {d28-d29},[r7,: 128]! +veor q5,q5,q6 +vld1.8 {d0},[r4,: 64] +veor q6,q7,q10 +vld1.8 {d2},[r5,: 64] +veor q7,q9,q10 +vld1.8 {d4},[r6,: 64] +veor q9,q11,q12 +vld1.8 {d6},[r7,: 64] +veor q10,q0,q1 +sub r2,r4,#32 +vand q9,q9,q8 +sub r4,r5,#32 +vand q10,q10,q8 +sub r5,r6,#32 +veor q11,q11,q9 +sub r6,r7,#32 +veor q0,q0,q10 +veor q9,q12,q9 +veor q1,q1,q10 +veor q10,q13,q14 +veor q12,q2,q3 +vand q10,q10,q8 +vand q8,q12,q8 +veor q12,q13,q10 +veor q2,q2,q8 +veor q10,q14,q10 +veor q3,q3,q8 +vadd.i32 q8,q4,q6 +vsub.i32 q4,q4,q6 +vst1.8 {d16-d17},[r2,: 128]! +vadd.i32 q6,q11,q12 +vst1.8 {d8-d9},[r5,: 128]! +vsub.i32 q4,q11,q12 +vst1.8 {d12-d13},[r2,: 128]! +vadd.i32 q6,q0,q2 +vst1.8 {d8-d9},[r5,: 128]! +vsub.i32 q0,q0,q2 +vst1.8 d12,[r2,: 64] +vadd.i32 q2,q5,q7 +vst1.8 d0,[r5,: 64] +vsub.i32 q0,q5,q7 +vst1.8 {d4-d5},[r4,: 128]! +vadd.i32 q2,q9,q10 +vst1.8 {d0-d1},[r6,: 128]! +vsub.i32 q0,q9,q10 +vst1.8 {d4-d5},[r4,: 128]! +vadd.i32 q2,q1,q3 +vst1.8 {d0-d1},[r6,: 128]! +vsub.i32 q0,q1,q3 +vst1.8 d4,[r4,: 64] +vst1.8 d0,[r6,: 64] +add r2,sp,#544 +add r4,r3,#96 +add r5,r3,#144 +vld1.8 {d0-d1},[r2,: 128] +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4-d5},[r5,: 128]! +vzip.i32 q1,q2 +vld1.8 {d6-d7},[r4,: 128]! +vld1.8 {d8-d9},[r5,: 128]! +vshl.i32 q5,q1,#1 +vzip.i32 q3,q4 +vshl.i32 q6,q2,#1 +vld1.8 {d14},[r4,: 64] +vshl.i32 q8,q3,#1 +vld1.8 {d15},[r5,: 64] +vshl.i32 q9,q4,#1 +vmul.i32 d21,d7,d1 +vtrn.32 d14,d15 +vmul.i32 q11,q4,q0 +vmul.i32 q0,q7,q0 +vmull.s32 q12,d2,d2 +vmlal.s32 q12,d11,d1 +vmlal.s32 q12,d12,d0 +vmlal.s32 q12,d13,d23 +vmlal.s32 q12,d16,d22 +vmlal.s32 q12,d7,d21 +vmull.s32 q10,d2,d11 +vmlal.s32 q10,d4,d1 +vmlal.s32 q10,d13,d0 +vmlal.s32 q10,d6,d23 +vmlal.s32 q10,d17,d22 +vmull.s32 q13,d10,d4 +vmlal.s32 q13,d11,d3 +vmlal.s32 q13,d13,d1 +vmlal.s32 q13,d16,d0 +vmlal.s32 q13,d17,d23 +vmlal.s32 q13,d8,d22 +vmull.s32 q1,d10,d5 +vmlal.s32 q1,d11,d4 +vmlal.s32 q1,d6,d1 +vmlal.s32 q1,d17,d0 +vmlal.s32 q1,d8,d23 +vmull.s32 q14,d10,d6 +vmlal.s32 q14,d11,d13 +vmlal.s32 q14,d4,d4 +vmlal.s32 q14,d17,d1 +vmlal.s32 q14,d18,d0 +vmlal.s32 q14,d9,d23 +vmull.s32 q11,d10,d7 +vmlal.s32 q11,d11,d6 +vmlal.s32 q11,d12,d5 +vmlal.s32 q11,d8,d1 +vmlal.s32 q11,d19,d0 +vmull.s32 q15,d10,d8 +vmlal.s32 q15,d11,d17 +vmlal.s32 q15,d12,d6 +vmlal.s32 q15,d13,d5 +vmlal.s32 q15,d19,d1 +vmlal.s32 q15,d14,d0 +vmull.s32 q2,d10,d9 +vmlal.s32 q2,d11,d8 +vmlal.s32 q2,d12,d7 +vmlal.s32 q2,d13,d6 +vmlal.s32 q2,d14,d1 +vmull.s32 q0,d15,d1 +vmlal.s32 q0,d10,d14 +vmlal.s32 q0,d11,d19 +vmlal.s32 q0,d12,d8 +vmlal.s32 q0,d13,d17 +vmlal.s32 q0,d6,d6 +add r2,sp,#512 +vld1.8 {d18-d19},[r2,: 128] +vmull.s32 q3,d16,d7 +vmlal.s32 q3,d10,d15 +vmlal.s32 q3,d11,d14 +vmlal.s32 q3,d12,d9 +vmlal.s32 q3,d13,d8 +add r2,sp,#528 +vld1.8 {d8-d9},[r2,: 128] +vadd.i64 q5,q12,q9 +vadd.i64 q6,q15,q9 +vshr.s64 q5,q5,#26 +vshr.s64 q6,q6,#26 +vadd.i64 q7,q10,q5 +vshl.i64 q5,q5,#26 +vadd.i64 q8,q7,q4 +vadd.i64 q2,q2,q6 +vshl.i64 q6,q6,#26 +vadd.i64 q10,q2,q4 +vsub.i64 q5,q12,q5 +vshr.s64 q8,q8,#25 +vsub.i64 q6,q15,q6 +vshr.s64 q10,q10,#25 +vadd.i64 q12,q13,q8 +vshl.i64 q8,q8,#25 +vadd.i64 q13,q12,q9 +vadd.i64 q0,q0,q10 +vsub.i64 q7,q7,q8 +vshr.s64 q8,q13,#26 +vshl.i64 q10,q10,#25 +vadd.i64 q13,q0,q9 +vadd.i64 q1,q1,q8 +vshl.i64 q8,q8,#26 +vadd.i64 q15,q1,q4 +vsub.i64 q2,q2,q10 +vshr.s64 q10,q13,#26 +vsub.i64 q8,q12,q8 +vshr.s64 q12,q15,#25 +vadd.i64 q3,q3,q10 +vshl.i64 q10,q10,#26 +vadd.i64 q13,q3,q4 +vadd.i64 q14,q14,q12 +add r2,r3,#288 +vshl.i64 q12,q12,#25 +add r4,r3,#336 +vadd.i64 q15,q14,q9 +add r2,r2,#8 +vsub.i64 q0,q0,q10 +add r4,r4,#8 +vshr.s64 q10,q13,#25 +vsub.i64 q1,q1,q12 +vshr.s64 q12,q15,#26 +vadd.i64 q13,q10,q10 +vadd.i64 q11,q11,q12 +vtrn.32 d16,d2 +vshl.i64 q12,q12,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q11,q4 +vadd.i64 q4,q5,q13 +vst1.8 d16,[r2,: 64]! +vshl.i64 q5,q10,#4 +vst1.8 d17,[r4,: 64]! +vsub.i64 q8,q14,q12 +vshr.s64 q1,q1,#25 +vadd.i64 q4,q4,q5 +vadd.i64 q5,q6,q1 +vshl.i64 q1,q1,#25 +vadd.i64 q6,q5,q9 +vadd.i64 q4,q4,q10 +vshl.i64 q10,q10,#25 +vadd.i64 q9,q4,q9 +vsub.i64 q1,q11,q1 +vshr.s64 q6,q6,#26 +vsub.i64 q3,q3,q10 +vtrn.32 d16,d2 +vshr.s64 q9,q9,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q2,q6 +vst1.8 d16,[r2,: 64] +vshl.i64 q2,q6,#26 +vst1.8 d17,[r4,: 64] +vadd.i64 q6,q7,q9 +vtrn.32 d0,d6 +vshl.i64 q7,q9,#26 +vtrn.32 d1,d7 +vsub.i64 q2,q5,q2 +add r2,r2,#16 +vsub.i64 q3,q4,q7 +vst1.8 d0,[r2,: 64] +add r4,r4,#16 +vst1.8 d1,[r4,: 64] +vtrn.32 d4,d2 +vtrn.32 d5,d3 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d6,d12 +vtrn.32 d7,d13 +vst1.8 d4,[r2,: 64] +vst1.8 d5,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d6,[r2,: 64] +vst1.8 d7,[r4,: 64] +add r2,r3,#240 +add r4,r3,#96 +vld1.8 {d0-d1},[r4,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4},[r4,: 64] +add r4,r3,#144 +vld1.8 {d6-d7},[r4,: 128]! +vtrn.32 q0,q3 +vld1.8 {d8-d9},[r4,: 128]! +vshl.i32 q5,q0,#4 +vtrn.32 q1,q4 +vshl.i32 q6,q3,#4 +vadd.i32 q5,q5,q0 +vadd.i32 q6,q6,q3 +vshl.i32 q7,q1,#4 +vld1.8 {d5},[r4,: 64] +vshl.i32 q8,q4,#4 +vtrn.32 d4,d5 +vadd.i32 q7,q7,q1 +vadd.i32 q8,q8,q4 +vld1.8 {d18-d19},[r2,: 128]! +vshl.i32 q10,q2,#4 +vld1.8 {d22-d23},[r2,: 128]! +vadd.i32 q10,q10,q2 +vld1.8 {d24},[r2,: 64] +vadd.i32 q5,q5,q0 +add r2,r3,#192 +vld1.8 {d26-d27},[r2,: 128]! +vadd.i32 q6,q6,q3 +vld1.8 {d28-d29},[r2,: 128]! +vadd.i32 q8,q8,q4 +vld1.8 {d25},[r2,: 64] +vadd.i32 q10,q10,q2 +vtrn.32 q9,q13 +vadd.i32 q7,q7,q1 +vadd.i32 q5,q5,q0 +vtrn.32 q11,q14 +vadd.i32 q6,q6,q3 +add r2,sp,#560 +vadd.i32 q10,q10,q2 +vtrn.32 d24,d25 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q6,q13,#1 +add r2,sp,#576 +vst1.8 {d20-d21},[r2,: 128] +vshl.i32 q10,q14,#1 +add r2,sp,#592 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q15,q12,#1 +vadd.i32 q8,q8,q4 +vext.32 d10,d31,d30,#0 +vadd.i32 q7,q7,q1 +add r2,sp,#608 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q8,d18,d5 +vmlal.s32 q8,d26,d4 +vmlal.s32 q8,d19,d9 +vmlal.s32 q8,d27,d3 +vmlal.s32 q8,d22,d8 +vmlal.s32 q8,d28,d2 +vmlal.s32 q8,d23,d7 +vmlal.s32 q8,d29,d1 +vmlal.s32 q8,d24,d6 +vmlal.s32 q8,d25,d0 +add r2,sp,#624 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q2,d18,d4 +vmlal.s32 q2,d12,d9 +vmlal.s32 q2,d13,d8 +vmlal.s32 q2,d19,d3 +vmlal.s32 q2,d22,d2 +vmlal.s32 q2,d23,d1 +vmlal.s32 q2,d24,d0 +add r2,sp,#640 +vst1.8 {d20-d21},[r2,: 128] +vmull.s32 q7,d18,d9 +vmlal.s32 q7,d26,d3 +vmlal.s32 q7,d19,d8 +vmlal.s32 q7,d27,d2 +vmlal.s32 q7,d22,d7 +vmlal.s32 q7,d28,d1 +vmlal.s32 q7,d23,d6 +vmlal.s32 q7,d29,d0 +add r2,sp,#656 +vst1.8 {d10-d11},[r2,: 128] +vmull.s32 q5,d18,d3 +vmlal.s32 q5,d19,d2 +vmlal.s32 q5,d22,d1 +vmlal.s32 q5,d23,d0 +vmlal.s32 q5,d12,d8 +add r2,sp,#672 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q4,d18,d8 +vmlal.s32 q4,d26,d2 +vmlal.s32 q4,d19,d7 +vmlal.s32 q4,d27,d1 +vmlal.s32 q4,d22,d6 +vmlal.s32 q4,d28,d0 +vmull.s32 q8,d18,d7 +vmlal.s32 q8,d26,d1 +vmlal.s32 q8,d19,d6 +vmlal.s32 q8,d27,d0 +add r2,sp,#576 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q7,d24,d21 +vmlal.s32 q7,d25,d20 +vmlal.s32 q4,d23,d21 +vmlal.s32 q4,d29,d20 +vmlal.s32 q8,d22,d21 +vmlal.s32 q8,d28,d20 +vmlal.s32 q5,d24,d20 +add r2,sp,#576 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q7,d18,d6 +vmlal.s32 q7,d26,d0 +add r2,sp,#656 +vld1.8 {d30-d31},[r2,: 128] +vmlal.s32 q2,d30,d21 +vmlal.s32 q7,d19,d21 +vmlal.s32 q7,d27,d20 +add r2,sp,#624 +vld1.8 {d26-d27},[r2,: 128] +vmlal.s32 q4,d25,d27 +vmlal.s32 q8,d29,d27 +vmlal.s32 q8,d25,d26 +vmlal.s32 q7,d28,d27 +vmlal.s32 q7,d29,d26 +add r2,sp,#608 +vld1.8 {d28-d29},[r2,: 128] +vmlal.s32 q4,d24,d29 +vmlal.s32 q8,d23,d29 +vmlal.s32 q8,d24,d28 +vmlal.s32 q7,d22,d29 +vmlal.s32 q7,d23,d28 +add r2,sp,#608 +vst1.8 {d8-d9},[r2,: 128] +add r2,sp,#560 +vld1.8 {d8-d9},[r2,: 128] +vmlal.s32 q7,d24,d9 +vmlal.s32 q7,d25,d31 +vmull.s32 q1,d18,d2 +vmlal.s32 q1,d19,d1 +vmlal.s32 q1,d22,d0 +vmlal.s32 q1,d24,d27 +vmlal.s32 q1,d23,d20 +vmlal.s32 q1,d12,d7 +vmlal.s32 q1,d13,d6 +vmull.s32 q6,d18,d1 +vmlal.s32 q6,d19,d0 +vmlal.s32 q6,d23,d27 +vmlal.s32 q6,d22,d20 +vmlal.s32 q6,d24,d26 +vmull.s32 q0,d18,d0 +vmlal.s32 q0,d22,d27 +vmlal.s32 q0,d23,d26 +vmlal.s32 q0,d24,d31 +vmlal.s32 q0,d19,d20 +add r2,sp,#640 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q2,d18,d7 +vmlal.s32 q2,d19,d6 +vmlal.s32 q5,d18,d6 +vmlal.s32 q5,d19,d21 +vmlal.s32 q1,d18,d21 +vmlal.s32 q1,d19,d29 +vmlal.s32 q0,d18,d28 +vmlal.s32 q0,d19,d9 +vmlal.s32 q6,d18,d29 +vmlal.s32 q6,d19,d28 +add r2,sp,#592 +vld1.8 {d18-d19},[r2,: 128] +add r2,sp,#512 +vld1.8 {d22-d23},[r2,: 128] +vmlal.s32 q5,d19,d7 +vmlal.s32 q0,d18,d21 +vmlal.s32 q0,d19,d29 +vmlal.s32 q6,d18,d6 +add r2,sp,#528 +vld1.8 {d6-d7},[r2,: 128] +vmlal.s32 q6,d19,d21 +add r2,sp,#576 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q0,d30,d8 +add r2,sp,#672 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q5,d30,d29 +add r2,sp,#608 +vld1.8 {d24-d25},[r2,: 128] +vmlal.s32 q1,d30,d28 +vadd.i64 q13,q0,q11 +vadd.i64 q14,q5,q11 +vmlal.s32 q6,d30,d9 +vshr.s64 q4,q13,#26 +vshr.s64 q13,q14,#26 +vadd.i64 q7,q7,q4 +vshl.i64 q4,q4,#26 +vadd.i64 q14,q7,q3 +vadd.i64 q9,q9,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q9,q3 +vsub.i64 q0,q0,q4 +vshr.s64 q4,q14,#25 +vsub.i64 q5,q5,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q4 +vshl.i64 q4,q4,#25 +vadd.i64 q14,q6,q11 +vadd.i64 q2,q2,q13 +vsub.i64 q4,q7,q4 +vshr.s64 q7,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q11 +vadd.i64 q8,q8,q7 +vshl.i64 q7,q7,#26 +vadd.i64 q15,q8,q3 +vsub.i64 q9,q9,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q7 +vshr.s64 q7,q15,#25 +vadd.i64 q10,q10,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q10,q3 +vadd.i64 q1,q1,q7 +add r2,r3,#144 +vshl.i64 q7,q7,#25 +add r4,r3,#96 +vadd.i64 q15,q1,q11 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +add r4,r4,#8 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q8,q7 +vshr.s64 q8,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q12,q12,q8 +vtrn.32 d12,d14 +vshl.i64 q8,q8,#26 +vtrn.32 d13,d15 +vadd.i64 q3,q12,q3 +vadd.i64 q0,q0,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q7,q13,#4 +vst1.8 d13,[r4,: 64]! +vsub.i64 q1,q1,q8 +vshr.s64 q3,q3,#25 +vadd.i64 q0,q0,q7 +vadd.i64 q5,q5,q3 +vshl.i64 q3,q3,#25 +vadd.i64 q6,q5,q11 +vadd.i64 q0,q0,q13 +vshl.i64 q7,q13,#25 +vadd.i64 q8,q0,q11 +vsub.i64 q3,q12,q3 +vshr.s64 q6,q6,#26 +vsub.i64 q7,q10,q7 +vtrn.32 d2,d6 +vshr.s64 q8,q8,#26 +vtrn.32 d3,d7 +vadd.i64 q3,q9,q6 +vst1.8 d2,[r2,: 64] +vshl.i64 q6,q6,#26 +vst1.8 d3,[r4,: 64] +vadd.i64 q1,q4,q8 +vtrn.32 d4,d14 +vshl.i64 q4,q8,#26 +vtrn.32 d5,d15 +vsub.i64 q5,q5,q6 +add r2,r2,#16 +vsub.i64 q0,q0,q4 +vst1.8 d4,[r2,: 64] +add r4,r4,#16 +vst1.8 d5,[r4,: 64] +vtrn.32 d10,d6 +vtrn.32 d11,d7 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d0,d2 +vtrn.32 d1,d3 +vst1.8 d10,[r2,: 64] +vst1.8 d11,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d0,[r2,: 64] +vst1.8 d1,[r4,: 64] +add r2,r3,#288 +add r4,r3,#336 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vsub.i32 q0,q0,q1 +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4-d5},[r4,: 128]! +vsub.i32 q1,q1,q2 +add r5,r3,#240 +vld1.8 {d4},[r2,: 64] +vld1.8 {d6},[r4,: 64] +vsub.i32 q2,q2,q3 +vst1.8 {d0-d1},[r5,: 128]! +vst1.8 {d2-d3},[r5,: 128]! +vst1.8 d4,[r5,: 64] +add r2,r3,#144 +add r4,r3,#96 +add r5,r3,#144 +add r6,r3,#192 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vsub.i32 q2,q0,q1 +vadd.i32 q0,q0,q1 +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d6-d7},[r4,: 128]! +vsub.i32 q4,q1,q3 +vadd.i32 q1,q1,q3 +vld1.8 {d6},[r2,: 64] +vld1.8 {d10},[r4,: 64] +vsub.i32 q6,q3,q5 +vadd.i32 q3,q3,q5 +vst1.8 {d4-d5},[r5,: 128]! +vst1.8 {d0-d1},[r6,: 128]! +vst1.8 {d8-d9},[r5,: 128]! +vst1.8 {d2-d3},[r6,: 128]! +vst1.8 d12,[r5,: 64] +vst1.8 d6,[r6,: 64] +add r2,r3,#0 +add r4,r3,#240 +vld1.8 {d0-d1},[r4,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4},[r4,: 64] +add r4,r3,#336 +vld1.8 {d6-d7},[r4,: 128]! +vtrn.32 q0,q3 +vld1.8 {d8-d9},[r4,: 128]! +vshl.i32 q5,q0,#4 +vtrn.32 q1,q4 +vshl.i32 q6,q3,#4 +vadd.i32 q5,q5,q0 +vadd.i32 q6,q6,q3 +vshl.i32 q7,q1,#4 +vld1.8 {d5},[r4,: 64] +vshl.i32 q8,q4,#4 +vtrn.32 d4,d5 +vadd.i32 q7,q7,q1 +vadd.i32 q8,q8,q4 +vld1.8 {d18-d19},[r2,: 128]! +vshl.i32 q10,q2,#4 +vld1.8 {d22-d23},[r2,: 128]! +vadd.i32 q10,q10,q2 +vld1.8 {d24},[r2,: 64] +vadd.i32 q5,q5,q0 +add r2,r3,#288 +vld1.8 {d26-d27},[r2,: 128]! +vadd.i32 q6,q6,q3 +vld1.8 {d28-d29},[r2,: 128]! +vadd.i32 q8,q8,q4 +vld1.8 {d25},[r2,: 64] +vadd.i32 q10,q10,q2 +vtrn.32 q9,q13 +vadd.i32 q7,q7,q1 +vadd.i32 q5,q5,q0 +vtrn.32 q11,q14 +vadd.i32 q6,q6,q3 +add r2,sp,#560 +vadd.i32 q10,q10,q2 +vtrn.32 d24,d25 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q6,q13,#1 +add r2,sp,#576 +vst1.8 {d20-d21},[r2,: 128] +vshl.i32 q10,q14,#1 +add r2,sp,#592 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q15,q12,#1 +vadd.i32 q8,q8,q4 +vext.32 d10,d31,d30,#0 +vadd.i32 q7,q7,q1 +add r2,sp,#608 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q8,d18,d5 +vmlal.s32 q8,d26,d4 +vmlal.s32 q8,d19,d9 +vmlal.s32 q8,d27,d3 +vmlal.s32 q8,d22,d8 +vmlal.s32 q8,d28,d2 +vmlal.s32 q8,d23,d7 +vmlal.s32 q8,d29,d1 +vmlal.s32 q8,d24,d6 +vmlal.s32 q8,d25,d0 +add r2,sp,#624 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q2,d18,d4 +vmlal.s32 q2,d12,d9 +vmlal.s32 q2,d13,d8 +vmlal.s32 q2,d19,d3 +vmlal.s32 q2,d22,d2 +vmlal.s32 q2,d23,d1 +vmlal.s32 q2,d24,d0 +add r2,sp,#640 +vst1.8 {d20-d21},[r2,: 128] +vmull.s32 q7,d18,d9 +vmlal.s32 q7,d26,d3 +vmlal.s32 q7,d19,d8 +vmlal.s32 q7,d27,d2 +vmlal.s32 q7,d22,d7 +vmlal.s32 q7,d28,d1 +vmlal.s32 q7,d23,d6 +vmlal.s32 q7,d29,d0 +add r2,sp,#656 +vst1.8 {d10-d11},[r2,: 128] +vmull.s32 q5,d18,d3 +vmlal.s32 q5,d19,d2 +vmlal.s32 q5,d22,d1 +vmlal.s32 q5,d23,d0 +vmlal.s32 q5,d12,d8 +add r2,sp,#672 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q4,d18,d8 +vmlal.s32 q4,d26,d2 +vmlal.s32 q4,d19,d7 +vmlal.s32 q4,d27,d1 +vmlal.s32 q4,d22,d6 +vmlal.s32 q4,d28,d0 +vmull.s32 q8,d18,d7 +vmlal.s32 q8,d26,d1 +vmlal.s32 q8,d19,d6 +vmlal.s32 q8,d27,d0 +add r2,sp,#576 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q7,d24,d21 +vmlal.s32 q7,d25,d20 +vmlal.s32 q4,d23,d21 +vmlal.s32 q4,d29,d20 +vmlal.s32 q8,d22,d21 +vmlal.s32 q8,d28,d20 +vmlal.s32 q5,d24,d20 +add r2,sp,#576 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q7,d18,d6 +vmlal.s32 q7,d26,d0 +add r2,sp,#656 +vld1.8 {d30-d31},[r2,: 128] +vmlal.s32 q2,d30,d21 +vmlal.s32 q7,d19,d21 +vmlal.s32 q7,d27,d20 +add r2,sp,#624 +vld1.8 {d26-d27},[r2,: 128] +vmlal.s32 q4,d25,d27 +vmlal.s32 q8,d29,d27 +vmlal.s32 q8,d25,d26 +vmlal.s32 q7,d28,d27 +vmlal.s32 q7,d29,d26 +add r2,sp,#608 +vld1.8 {d28-d29},[r2,: 128] +vmlal.s32 q4,d24,d29 +vmlal.s32 q8,d23,d29 +vmlal.s32 q8,d24,d28 +vmlal.s32 q7,d22,d29 +vmlal.s32 q7,d23,d28 +add r2,sp,#608 +vst1.8 {d8-d9},[r2,: 128] +add r2,sp,#560 +vld1.8 {d8-d9},[r2,: 128] +vmlal.s32 q7,d24,d9 +vmlal.s32 q7,d25,d31 +vmull.s32 q1,d18,d2 +vmlal.s32 q1,d19,d1 +vmlal.s32 q1,d22,d0 +vmlal.s32 q1,d24,d27 +vmlal.s32 q1,d23,d20 +vmlal.s32 q1,d12,d7 +vmlal.s32 q1,d13,d6 +vmull.s32 q6,d18,d1 +vmlal.s32 q6,d19,d0 +vmlal.s32 q6,d23,d27 +vmlal.s32 q6,d22,d20 +vmlal.s32 q6,d24,d26 +vmull.s32 q0,d18,d0 +vmlal.s32 q0,d22,d27 +vmlal.s32 q0,d23,d26 +vmlal.s32 q0,d24,d31 +vmlal.s32 q0,d19,d20 +add r2,sp,#640 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q2,d18,d7 +vmlal.s32 q2,d19,d6 +vmlal.s32 q5,d18,d6 +vmlal.s32 q5,d19,d21 +vmlal.s32 q1,d18,d21 +vmlal.s32 q1,d19,d29 +vmlal.s32 q0,d18,d28 +vmlal.s32 q0,d19,d9 +vmlal.s32 q6,d18,d29 +vmlal.s32 q6,d19,d28 +add r2,sp,#592 +vld1.8 {d18-d19},[r2,: 128] +add r2,sp,#512 +vld1.8 {d22-d23},[r2,: 128] +vmlal.s32 q5,d19,d7 +vmlal.s32 q0,d18,d21 +vmlal.s32 q0,d19,d29 +vmlal.s32 q6,d18,d6 +add r2,sp,#528 +vld1.8 {d6-d7},[r2,: 128] +vmlal.s32 q6,d19,d21 +add r2,sp,#576 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q0,d30,d8 +add r2,sp,#672 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q5,d30,d29 +add r2,sp,#608 +vld1.8 {d24-d25},[r2,: 128] +vmlal.s32 q1,d30,d28 +vadd.i64 q13,q0,q11 +vadd.i64 q14,q5,q11 +vmlal.s32 q6,d30,d9 +vshr.s64 q4,q13,#26 +vshr.s64 q13,q14,#26 +vadd.i64 q7,q7,q4 +vshl.i64 q4,q4,#26 +vadd.i64 q14,q7,q3 +vadd.i64 q9,q9,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q9,q3 +vsub.i64 q0,q0,q4 +vshr.s64 q4,q14,#25 +vsub.i64 q5,q5,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q4 +vshl.i64 q4,q4,#25 +vadd.i64 q14,q6,q11 +vadd.i64 q2,q2,q13 +vsub.i64 q4,q7,q4 +vshr.s64 q7,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q11 +vadd.i64 q8,q8,q7 +vshl.i64 q7,q7,#26 +vadd.i64 q15,q8,q3 +vsub.i64 q9,q9,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q7 +vshr.s64 q7,q15,#25 +vadd.i64 q10,q10,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q10,q3 +vadd.i64 q1,q1,q7 +add r2,r3,#288 +vshl.i64 q7,q7,#25 +add r4,r3,#96 +vadd.i64 q15,q1,q11 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +add r4,r4,#8 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q8,q7 +vshr.s64 q8,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q12,q12,q8 +vtrn.32 d12,d14 +vshl.i64 q8,q8,#26 +vtrn.32 d13,d15 +vadd.i64 q3,q12,q3 +vadd.i64 q0,q0,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q7,q13,#4 +vst1.8 d13,[r4,: 64]! +vsub.i64 q1,q1,q8 +vshr.s64 q3,q3,#25 +vadd.i64 q0,q0,q7 +vadd.i64 q5,q5,q3 +vshl.i64 q3,q3,#25 +vadd.i64 q6,q5,q11 +vadd.i64 q0,q0,q13 +vshl.i64 q7,q13,#25 +vadd.i64 q8,q0,q11 +vsub.i64 q3,q12,q3 +vshr.s64 q6,q6,#26 +vsub.i64 q7,q10,q7 +vtrn.32 d2,d6 +vshr.s64 q8,q8,#26 +vtrn.32 d3,d7 +vadd.i64 q3,q9,q6 +vst1.8 d2,[r2,: 64] +vshl.i64 q6,q6,#26 +vst1.8 d3,[r4,: 64] +vadd.i64 q1,q4,q8 +vtrn.32 d4,d14 +vshl.i64 q4,q8,#26 +vtrn.32 d5,d15 +vsub.i64 q5,q5,q6 +add r2,r2,#16 +vsub.i64 q0,q0,q4 +vst1.8 d4,[r2,: 64] +add r4,r4,#16 +vst1.8 d5,[r4,: 64] +vtrn.32 d10,d6 +vtrn.32 d11,d7 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d0,d2 +vtrn.32 d1,d3 +vst1.8 d10,[r2,: 64] +vst1.8 d11,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d0,[r2,: 64] +vst1.8 d1,[r4,: 64] +add r2,sp,#544 +add r4,r3,#144 +add r5,r3,#192 +vld1.8 {d0-d1},[r2,: 128] +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4-d5},[r5,: 128]! +vzip.i32 q1,q2 +vld1.8 {d6-d7},[r4,: 128]! +vld1.8 {d8-d9},[r5,: 128]! +vshl.i32 q5,q1,#1 +vzip.i32 q3,q4 +vshl.i32 q6,q2,#1 +vld1.8 {d14},[r4,: 64] +vshl.i32 q8,q3,#1 +vld1.8 {d15},[r5,: 64] +vshl.i32 q9,q4,#1 +vmul.i32 d21,d7,d1 +vtrn.32 d14,d15 +vmul.i32 q11,q4,q0 +vmul.i32 q0,q7,q0 +vmull.s32 q12,d2,d2 +vmlal.s32 q12,d11,d1 +vmlal.s32 q12,d12,d0 +vmlal.s32 q12,d13,d23 +vmlal.s32 q12,d16,d22 +vmlal.s32 q12,d7,d21 +vmull.s32 q10,d2,d11 +vmlal.s32 q10,d4,d1 +vmlal.s32 q10,d13,d0 +vmlal.s32 q10,d6,d23 +vmlal.s32 q10,d17,d22 +vmull.s32 q13,d10,d4 +vmlal.s32 q13,d11,d3 +vmlal.s32 q13,d13,d1 +vmlal.s32 q13,d16,d0 +vmlal.s32 q13,d17,d23 +vmlal.s32 q13,d8,d22 +vmull.s32 q1,d10,d5 +vmlal.s32 q1,d11,d4 +vmlal.s32 q1,d6,d1 +vmlal.s32 q1,d17,d0 +vmlal.s32 q1,d8,d23 +vmull.s32 q14,d10,d6 +vmlal.s32 q14,d11,d13 +vmlal.s32 q14,d4,d4 +vmlal.s32 q14,d17,d1 +vmlal.s32 q14,d18,d0 +vmlal.s32 q14,d9,d23 +vmull.s32 q11,d10,d7 +vmlal.s32 q11,d11,d6 +vmlal.s32 q11,d12,d5 +vmlal.s32 q11,d8,d1 +vmlal.s32 q11,d19,d0 +vmull.s32 q15,d10,d8 +vmlal.s32 q15,d11,d17 +vmlal.s32 q15,d12,d6 +vmlal.s32 q15,d13,d5 +vmlal.s32 q15,d19,d1 +vmlal.s32 q15,d14,d0 +vmull.s32 q2,d10,d9 +vmlal.s32 q2,d11,d8 +vmlal.s32 q2,d12,d7 +vmlal.s32 q2,d13,d6 +vmlal.s32 q2,d14,d1 +vmull.s32 q0,d15,d1 +vmlal.s32 q0,d10,d14 +vmlal.s32 q0,d11,d19 +vmlal.s32 q0,d12,d8 +vmlal.s32 q0,d13,d17 +vmlal.s32 q0,d6,d6 +add r2,sp,#512 +vld1.8 {d18-d19},[r2,: 128] +vmull.s32 q3,d16,d7 +vmlal.s32 q3,d10,d15 +vmlal.s32 q3,d11,d14 +vmlal.s32 q3,d12,d9 +vmlal.s32 q3,d13,d8 +add r2,sp,#528 +vld1.8 {d8-d9},[r2,: 128] +vadd.i64 q5,q12,q9 +vadd.i64 q6,q15,q9 +vshr.s64 q5,q5,#26 +vshr.s64 q6,q6,#26 +vadd.i64 q7,q10,q5 +vshl.i64 q5,q5,#26 +vadd.i64 q8,q7,q4 +vadd.i64 q2,q2,q6 +vshl.i64 q6,q6,#26 +vadd.i64 q10,q2,q4 +vsub.i64 q5,q12,q5 +vshr.s64 q8,q8,#25 +vsub.i64 q6,q15,q6 +vshr.s64 q10,q10,#25 +vadd.i64 q12,q13,q8 +vshl.i64 q8,q8,#25 +vadd.i64 q13,q12,q9 +vadd.i64 q0,q0,q10 +vsub.i64 q7,q7,q8 +vshr.s64 q8,q13,#26 +vshl.i64 q10,q10,#25 +vadd.i64 q13,q0,q9 +vadd.i64 q1,q1,q8 +vshl.i64 q8,q8,#26 +vadd.i64 q15,q1,q4 +vsub.i64 q2,q2,q10 +vshr.s64 q10,q13,#26 +vsub.i64 q8,q12,q8 +vshr.s64 q12,q15,#25 +vadd.i64 q3,q3,q10 +vshl.i64 q10,q10,#26 +vadd.i64 q13,q3,q4 +vadd.i64 q14,q14,q12 +add r2,r3,#144 +vshl.i64 q12,q12,#25 +add r4,r3,#192 +vadd.i64 q15,q14,q9 +add r2,r2,#8 +vsub.i64 q0,q0,q10 +add r4,r4,#8 +vshr.s64 q10,q13,#25 +vsub.i64 q1,q1,q12 +vshr.s64 q12,q15,#26 +vadd.i64 q13,q10,q10 +vadd.i64 q11,q11,q12 +vtrn.32 d16,d2 +vshl.i64 q12,q12,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q11,q4 +vadd.i64 q4,q5,q13 +vst1.8 d16,[r2,: 64]! +vshl.i64 q5,q10,#4 +vst1.8 d17,[r4,: 64]! +vsub.i64 q8,q14,q12 +vshr.s64 q1,q1,#25 +vadd.i64 q4,q4,q5 +vadd.i64 q5,q6,q1 +vshl.i64 q1,q1,#25 +vadd.i64 q6,q5,q9 +vadd.i64 q4,q4,q10 +vshl.i64 q10,q10,#25 +vadd.i64 q9,q4,q9 +vsub.i64 q1,q11,q1 +vshr.s64 q6,q6,#26 +vsub.i64 q3,q3,q10 +vtrn.32 d16,d2 +vshr.s64 q9,q9,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q2,q6 +vst1.8 d16,[r2,: 64] +vshl.i64 q2,q6,#26 +vst1.8 d17,[r4,: 64] +vadd.i64 q6,q7,q9 +vtrn.32 d0,d6 +vshl.i64 q7,q9,#26 +vtrn.32 d1,d7 +vsub.i64 q2,q5,q2 +add r2,r2,#16 +vsub.i64 q3,q4,q7 +vst1.8 d0,[r2,: 64] +add r4,r4,#16 +vst1.8 d1,[r4,: 64] +vtrn.32 d4,d2 +vtrn.32 d5,d3 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d6,d12 +vtrn.32 d7,d13 +vst1.8 d4,[r2,: 64] +vst1.8 d5,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d6,[r2,: 64] +vst1.8 d7,[r4,: 64] +add r2,r3,#336 +add r4,r3,#288 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vadd.i32 q0,q0,q1 +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4-d5},[r4,: 128]! +vadd.i32 q1,q1,q2 +add r5,r3,#288 +vld1.8 {d4},[r2,: 64] +vld1.8 {d6},[r4,: 64] +vadd.i32 q2,q2,q3 +vst1.8 {d0-d1},[r5,: 128]! +vst1.8 {d2-d3},[r5,: 128]! +vst1.8 d4,[r5,: 64] +add r2,r3,#48 +add r4,r3,#144 +vld1.8 {d0-d1},[r4,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4},[r4,: 64] +add r4,r3,#288 +vld1.8 {d6-d7},[r4,: 128]! +vtrn.32 q0,q3 +vld1.8 {d8-d9},[r4,: 128]! +vshl.i32 q5,q0,#4 +vtrn.32 q1,q4 +vshl.i32 q6,q3,#4 +vadd.i32 q5,q5,q0 +vadd.i32 q6,q6,q3 +vshl.i32 q7,q1,#4 +vld1.8 {d5},[r4,: 64] +vshl.i32 q8,q4,#4 +vtrn.32 d4,d5 +vadd.i32 q7,q7,q1 +vadd.i32 q8,q8,q4 +vld1.8 {d18-d19},[r2,: 128]! +vshl.i32 q10,q2,#4 +vld1.8 {d22-d23},[r2,: 128]! +vadd.i32 q10,q10,q2 +vld1.8 {d24},[r2,: 64] +vadd.i32 q5,q5,q0 +add r2,r3,#240 +vld1.8 {d26-d27},[r2,: 128]! +vadd.i32 q6,q6,q3 +vld1.8 {d28-d29},[r2,: 128]! +vadd.i32 q8,q8,q4 +vld1.8 {d25},[r2,: 64] +vadd.i32 q10,q10,q2 +vtrn.32 q9,q13 +vadd.i32 q7,q7,q1 +vadd.i32 q5,q5,q0 +vtrn.32 q11,q14 +vadd.i32 q6,q6,q3 +add r2,sp,#560 +vadd.i32 q10,q10,q2 +vtrn.32 d24,d25 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q6,q13,#1 +add r2,sp,#576 +vst1.8 {d20-d21},[r2,: 128] +vshl.i32 q10,q14,#1 +add r2,sp,#592 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q15,q12,#1 +vadd.i32 q8,q8,q4 +vext.32 d10,d31,d30,#0 +vadd.i32 q7,q7,q1 +add r2,sp,#608 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q8,d18,d5 +vmlal.s32 q8,d26,d4 +vmlal.s32 q8,d19,d9 +vmlal.s32 q8,d27,d3 +vmlal.s32 q8,d22,d8 +vmlal.s32 q8,d28,d2 +vmlal.s32 q8,d23,d7 +vmlal.s32 q8,d29,d1 +vmlal.s32 q8,d24,d6 +vmlal.s32 q8,d25,d0 +add r2,sp,#624 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q2,d18,d4 +vmlal.s32 q2,d12,d9 +vmlal.s32 q2,d13,d8 +vmlal.s32 q2,d19,d3 +vmlal.s32 q2,d22,d2 +vmlal.s32 q2,d23,d1 +vmlal.s32 q2,d24,d0 +add r2,sp,#640 +vst1.8 {d20-d21},[r2,: 128] +vmull.s32 q7,d18,d9 +vmlal.s32 q7,d26,d3 +vmlal.s32 q7,d19,d8 +vmlal.s32 q7,d27,d2 +vmlal.s32 q7,d22,d7 +vmlal.s32 q7,d28,d1 +vmlal.s32 q7,d23,d6 +vmlal.s32 q7,d29,d0 +add r2,sp,#656 +vst1.8 {d10-d11},[r2,: 128] +vmull.s32 q5,d18,d3 +vmlal.s32 q5,d19,d2 +vmlal.s32 q5,d22,d1 +vmlal.s32 q5,d23,d0 +vmlal.s32 q5,d12,d8 +add r2,sp,#672 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q4,d18,d8 +vmlal.s32 q4,d26,d2 +vmlal.s32 q4,d19,d7 +vmlal.s32 q4,d27,d1 +vmlal.s32 q4,d22,d6 +vmlal.s32 q4,d28,d0 +vmull.s32 q8,d18,d7 +vmlal.s32 q8,d26,d1 +vmlal.s32 q8,d19,d6 +vmlal.s32 q8,d27,d0 +add r2,sp,#576 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q7,d24,d21 +vmlal.s32 q7,d25,d20 +vmlal.s32 q4,d23,d21 +vmlal.s32 q4,d29,d20 +vmlal.s32 q8,d22,d21 +vmlal.s32 q8,d28,d20 +vmlal.s32 q5,d24,d20 +add r2,sp,#576 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q7,d18,d6 +vmlal.s32 q7,d26,d0 +add r2,sp,#656 +vld1.8 {d30-d31},[r2,: 128] +vmlal.s32 q2,d30,d21 +vmlal.s32 q7,d19,d21 +vmlal.s32 q7,d27,d20 +add r2,sp,#624 +vld1.8 {d26-d27},[r2,: 128] +vmlal.s32 q4,d25,d27 +vmlal.s32 q8,d29,d27 +vmlal.s32 q8,d25,d26 +vmlal.s32 q7,d28,d27 +vmlal.s32 q7,d29,d26 +add r2,sp,#608 +vld1.8 {d28-d29},[r2,: 128] +vmlal.s32 q4,d24,d29 +vmlal.s32 q8,d23,d29 +vmlal.s32 q8,d24,d28 +vmlal.s32 q7,d22,d29 +vmlal.s32 q7,d23,d28 +add r2,sp,#608 +vst1.8 {d8-d9},[r2,: 128] +add r2,sp,#560 +vld1.8 {d8-d9},[r2,: 128] +vmlal.s32 q7,d24,d9 +vmlal.s32 q7,d25,d31 +vmull.s32 q1,d18,d2 +vmlal.s32 q1,d19,d1 +vmlal.s32 q1,d22,d0 +vmlal.s32 q1,d24,d27 +vmlal.s32 q1,d23,d20 +vmlal.s32 q1,d12,d7 +vmlal.s32 q1,d13,d6 +vmull.s32 q6,d18,d1 +vmlal.s32 q6,d19,d0 +vmlal.s32 q6,d23,d27 +vmlal.s32 q6,d22,d20 +vmlal.s32 q6,d24,d26 +vmull.s32 q0,d18,d0 +vmlal.s32 q0,d22,d27 +vmlal.s32 q0,d23,d26 +vmlal.s32 q0,d24,d31 +vmlal.s32 q0,d19,d20 +add r2,sp,#640 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q2,d18,d7 +vmlal.s32 q2,d19,d6 +vmlal.s32 q5,d18,d6 +vmlal.s32 q5,d19,d21 +vmlal.s32 q1,d18,d21 +vmlal.s32 q1,d19,d29 +vmlal.s32 q0,d18,d28 +vmlal.s32 q0,d19,d9 +vmlal.s32 q6,d18,d29 +vmlal.s32 q6,d19,d28 +add r2,sp,#592 +vld1.8 {d18-d19},[r2,: 128] +add r2,sp,#512 +vld1.8 {d22-d23},[r2,: 128] +vmlal.s32 q5,d19,d7 +vmlal.s32 q0,d18,d21 +vmlal.s32 q0,d19,d29 +vmlal.s32 q6,d18,d6 +add r2,sp,#528 +vld1.8 {d6-d7},[r2,: 128] +vmlal.s32 q6,d19,d21 +add r2,sp,#576 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q0,d30,d8 +add r2,sp,#672 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q5,d30,d29 +add r2,sp,#608 +vld1.8 {d24-d25},[r2,: 128] +vmlal.s32 q1,d30,d28 +vadd.i64 q13,q0,q11 +vadd.i64 q14,q5,q11 +vmlal.s32 q6,d30,d9 +vshr.s64 q4,q13,#26 +vshr.s64 q13,q14,#26 +vadd.i64 q7,q7,q4 +vshl.i64 q4,q4,#26 +vadd.i64 q14,q7,q3 +vadd.i64 q9,q9,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q9,q3 +vsub.i64 q0,q0,q4 +vshr.s64 q4,q14,#25 +vsub.i64 q5,q5,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q4 +vshl.i64 q4,q4,#25 +vadd.i64 q14,q6,q11 +vadd.i64 q2,q2,q13 +vsub.i64 q4,q7,q4 +vshr.s64 q7,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q11 +vadd.i64 q8,q8,q7 +vshl.i64 q7,q7,#26 +vadd.i64 q15,q8,q3 +vsub.i64 q9,q9,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q7 +vshr.s64 q7,q15,#25 +vadd.i64 q10,q10,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q10,q3 +vadd.i64 q1,q1,q7 +add r2,r3,#240 +vshl.i64 q7,q7,#25 +add r4,r3,#144 +vadd.i64 q15,q1,q11 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +add r4,r4,#8 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q8,q7 +vshr.s64 q8,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q12,q12,q8 +vtrn.32 d12,d14 +vshl.i64 q8,q8,#26 +vtrn.32 d13,d15 +vadd.i64 q3,q12,q3 +vadd.i64 q0,q0,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q7,q13,#4 +vst1.8 d13,[r4,: 64]! +vsub.i64 q1,q1,q8 +vshr.s64 q3,q3,#25 +vadd.i64 q0,q0,q7 +vadd.i64 q5,q5,q3 +vshl.i64 q3,q3,#25 +vadd.i64 q6,q5,q11 +vadd.i64 q0,q0,q13 +vshl.i64 q7,q13,#25 +vadd.i64 q8,q0,q11 +vsub.i64 q3,q12,q3 +vshr.s64 q6,q6,#26 +vsub.i64 q7,q10,q7 +vtrn.32 d2,d6 +vshr.s64 q8,q8,#26 +vtrn.32 d3,d7 +vadd.i64 q3,q9,q6 +vst1.8 d2,[r2,: 64] +vshl.i64 q6,q6,#26 +vst1.8 d3,[r4,: 64] +vadd.i64 q1,q4,q8 +vtrn.32 d4,d14 +vshl.i64 q4,q8,#26 +vtrn.32 d5,d15 +vsub.i64 q5,q5,q6 +add r2,r2,#16 +vsub.i64 q0,q0,q4 +vst1.8 d4,[r2,: 64] +add r4,r4,#16 +vst1.8 d5,[r4,: 64] +vtrn.32 d10,d6 +vtrn.32 d11,d7 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d0,d2 +vtrn.32 d1,d3 +vst1.8 d10,[r2,: 64] +vst1.8 d11,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d0,[r2,: 64] +vst1.8 d1,[r4,: 64] +ldr r2,[sp,#488] +ldr r4,[sp,#492] +subs r5,r2,#1 +bge ._mainloop +add r1,r3,#144 +add r2,r3,#336 +vld1.8 {d0-d1},[r1,: 128]! +vld1.8 {d2-d3},[r1,: 128]! +vld1.8 {d4},[r1,: 64] +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 {d2-d3},[r2,: 128]! +vst1.8 d4,[r2,: 64] +ldr r1,=0 +._invertloop: +add r2,r3,#144 +ldr r4,=0 +ldr r5,=2 +cmp r1,#1 +ldreq r5,=1 +addeq r2,r3,#336 +addeq r4,r3,#48 +cmp r1,#2 +ldreq r5,=1 +addeq r2,r3,#48 +cmp r1,#3 +ldreq r5,=5 +addeq r4,r3,#336 +cmp r1,#4 +ldreq r5,=10 +cmp r1,#5 +ldreq r5,=20 +cmp r1,#6 +ldreq r5,=10 +addeq r2,r3,#336 +addeq r4,r3,#336 +cmp r1,#7 +ldreq r5,=50 +cmp r1,#8 +ldreq r5,=100 +cmp r1,#9 +ldreq r5,=50 +addeq r2,r3,#336 +cmp r1,#10 +ldreq r5,=5 +addeq r2,r3,#48 +cmp r1,#11 +ldreq r5,=0 +addeq r2,r3,#96 +add r6,r3,#144 +add r7,r3,#288 +vld1.8 {d0-d1},[r6,: 128]! +vld1.8 {d2-d3},[r6,: 128]! +vld1.8 {d4},[r6,: 64] +vst1.8 {d0-d1},[r7,: 128]! +vst1.8 {d2-d3},[r7,: 128]! +vst1.8 d4,[r7,: 64] +cmp r5,#0 +beq ._skipsquaringloop +._squaringloop: +add r6,r3,#288 +add r7,r3,#288 +add r8,r3,#288 +vmov.i32 q0,#19 +vmov.i32 q1,#0 +vmov.i32 q2,#1 +vzip.i32 q1,q2 +vld1.8 {d4-d5},[r7,: 128]! +vld1.8 {d6-d7},[r7,: 128]! +vld1.8 {d9},[r7,: 64] +vld1.8 {d10-d11},[r6,: 128]! +add r7,sp,#416 +vld1.8 {d12-d13},[r6,: 128]! +vmul.i32 q7,q2,q0 +vld1.8 {d8},[r6,: 64] +vext.32 d17,d11,d10,#1 +vmul.i32 q9,q3,q0 +vext.32 d16,d10,d8,#1 +vshl.u32 q10,q5,q1 +vext.32 d22,d14,d4,#1 +vext.32 d24,d18,d6,#1 +vshl.u32 q13,q6,q1 +vshl.u32 d28,d8,d2 +vrev64.i32 d22,d22 +vmul.i32 d1,d9,d1 +vrev64.i32 d24,d24 +vext.32 d29,d8,d13,#1 +vext.32 d0,d1,d9,#1 +vrev64.i32 d0,d0 +vext.32 d2,d9,d1,#1 +vext.32 d23,d15,d5,#1 +vmull.s32 q4,d20,d4 +vrev64.i32 d23,d23 +vmlal.s32 q4,d21,d1 +vrev64.i32 d2,d2 +vmlal.s32 q4,d26,d19 +vext.32 d3,d5,d15,#1 +vmlal.s32 q4,d27,d18 +vrev64.i32 d3,d3 +vmlal.s32 q4,d28,d15 +vext.32 d14,d12,d11,#1 +vmull.s32 q5,d16,d23 +vext.32 d15,d13,d12,#1 +vmlal.s32 q5,d17,d4 +vst1.8 d8,[r7,: 64]! +vmlal.s32 q5,d14,d1 +vext.32 d12,d9,d8,#0 +vmlal.s32 q5,d15,d19 +vmov.i64 d13,#0 +vmlal.s32 q5,d29,d18 +vext.32 d25,d19,d7,#1 +vmlal.s32 q6,d20,d5 +vrev64.i32 d25,d25 +vmlal.s32 q6,d21,d4 +vst1.8 d11,[r7,: 64]! +vmlal.s32 q6,d26,d1 +vext.32 d9,d10,d10,#0 +vmlal.s32 q6,d27,d19 +vmov.i64 d8,#0 +vmlal.s32 q6,d28,d18 +vmlal.s32 q4,d16,d24 +vmlal.s32 q4,d17,d5 +vmlal.s32 q4,d14,d4 +vst1.8 d12,[r7,: 64]! +vmlal.s32 q4,d15,d1 +vext.32 d10,d13,d12,#0 +vmlal.s32 q4,d29,d19 +vmov.i64 d11,#0 +vmlal.s32 q5,d20,d6 +vmlal.s32 q5,d21,d5 +vmlal.s32 q5,d26,d4 +vext.32 d13,d8,d8,#0 +vmlal.s32 q5,d27,d1 +vmov.i64 d12,#0 +vmlal.s32 q5,d28,d19 +vst1.8 d9,[r7,: 64]! +vmlal.s32 q6,d16,d25 +vmlal.s32 q6,d17,d6 +vst1.8 d10,[r7,: 64] +vmlal.s32 q6,d14,d5 +vext.32 d8,d11,d10,#0 +vmlal.s32 q6,d15,d4 +vmov.i64 d9,#0 +vmlal.s32 q6,d29,d1 +vmlal.s32 q4,d20,d7 +vmlal.s32 q4,d21,d6 +vmlal.s32 q4,d26,d5 +vext.32 d11,d12,d12,#0 +vmlal.s32 q4,d27,d4 +vmov.i64 d10,#0 +vmlal.s32 q4,d28,d1 +vmlal.s32 q5,d16,d0 +sub r6,r7,#32 +vmlal.s32 q5,d17,d7 +vmlal.s32 q5,d14,d6 +vext.32 d30,d9,d8,#0 +vmlal.s32 q5,d15,d5 +vld1.8 {d31},[r6,: 64]! +vmlal.s32 q5,d29,d4 +vmlal.s32 q15,d20,d0 +vext.32 d0,d6,d18,#1 +vmlal.s32 q15,d21,d25 +vrev64.i32 d0,d0 +vmlal.s32 q15,d26,d24 +vext.32 d1,d7,d19,#1 +vext.32 d7,d10,d10,#0 +vmlal.s32 q15,d27,d23 +vrev64.i32 d1,d1 +vld1.8 {d6},[r6,: 64] +vmlal.s32 q15,d28,d22 +vmlal.s32 q3,d16,d4 +add r6,r6,#24 +vmlal.s32 q3,d17,d2 +vext.32 d4,d31,d30,#0 +vmov d17,d11 +vmlal.s32 q3,d14,d1 +vext.32 d11,d13,d13,#0 +vext.32 d13,d30,d30,#0 +vmlal.s32 q3,d15,d0 +vext.32 d1,d8,d8,#0 +vmlal.s32 q3,d29,d3 +vld1.8 {d5},[r6,: 64] +sub r6,r6,#16 +vext.32 d10,d6,d6,#0 +vmov.i32 q1,#0xffffffff +vshl.i64 q4,q1,#25 +add r7,sp,#512 +vld1.8 {d14-d15},[r7,: 128] +vadd.i64 q9,q2,q7 +vshl.i64 q1,q1,#26 +vshr.s64 q10,q9,#26 +vld1.8 {d0},[r6,: 64]! +vadd.i64 q5,q5,q10 +vand q9,q9,q1 +vld1.8 {d16},[r6,: 64]! +add r6,sp,#528 +vld1.8 {d20-d21},[r6,: 128] +vadd.i64 q11,q5,q10 +vsub.i64 q2,q2,q9 +vshr.s64 q9,q11,#25 +vext.32 d12,d5,d4,#0 +vand q11,q11,q4 +vadd.i64 q0,q0,q9 +vmov d19,d7 +vadd.i64 q3,q0,q7 +vsub.i64 q5,q5,q11 +vshr.s64 q11,q3,#26 +vext.32 d18,d11,d10,#0 +vand q3,q3,q1 +vadd.i64 q8,q8,q11 +vadd.i64 q11,q8,q10 +vsub.i64 q0,q0,q3 +vshr.s64 q3,q11,#25 +vand q11,q11,q4 +vadd.i64 q3,q6,q3 +vadd.i64 q6,q3,q7 +vsub.i64 q8,q8,q11 +vshr.s64 q11,q6,#26 +vand q6,q6,q1 +vadd.i64 q9,q9,q11 +vadd.i64 d25,d19,d21 +vsub.i64 q3,q3,q6 +vshr.s64 d23,d25,#25 +vand q4,q12,q4 +vadd.i64 d21,d23,d23 +vshl.i64 d25,d23,#4 +vadd.i64 d21,d21,d23 +vadd.i64 d25,d25,d21 +vadd.i64 d4,d4,d25 +vzip.i32 q0,q8 +vadd.i64 d12,d4,d14 +add r6,r8,#8 +vst1.8 d0,[r6,: 64] +vsub.i64 d19,d19,d9 +add r6,r6,#16 +vst1.8 d16,[r6,: 64] +vshr.s64 d22,d12,#26 +vand q0,q6,q1 +vadd.i64 d10,d10,d22 +vzip.i32 q3,q9 +vsub.i64 d4,d4,d0 +sub r6,r6,#8 +vst1.8 d6,[r6,: 64] +add r6,r6,#16 +vst1.8 d18,[r6,: 64] +vzip.i32 q2,q5 +sub r6,r6,#32 +vst1.8 d4,[r6,: 64] +subs r5,r5,#1 +bhi ._squaringloop +._skipsquaringloop: +mov r2,r2 +add r5,r3,#288 +add r6,r3,#144 +vmov.i32 q0,#19 +vmov.i32 q1,#0 +vmov.i32 q2,#1 +vzip.i32 q1,q2 +vld1.8 {d4-d5},[r5,: 128]! +vld1.8 {d6-d7},[r5,: 128]! +vld1.8 {d9},[r5,: 64] +vld1.8 {d10-d11},[r2,: 128]! +add r5,sp,#416 +vld1.8 {d12-d13},[r2,: 128]! +vmul.i32 q7,q2,q0 +vld1.8 {d8},[r2,: 64] +vext.32 d17,d11,d10,#1 +vmul.i32 q9,q3,q0 +vext.32 d16,d10,d8,#1 +vshl.u32 q10,q5,q1 +vext.32 d22,d14,d4,#1 +vext.32 d24,d18,d6,#1 +vshl.u32 q13,q6,q1 +vshl.u32 d28,d8,d2 +vrev64.i32 d22,d22 +vmul.i32 d1,d9,d1 +vrev64.i32 d24,d24 +vext.32 d29,d8,d13,#1 +vext.32 d0,d1,d9,#1 +vrev64.i32 d0,d0 +vext.32 d2,d9,d1,#1 +vext.32 d23,d15,d5,#1 +vmull.s32 q4,d20,d4 +vrev64.i32 d23,d23 +vmlal.s32 q4,d21,d1 +vrev64.i32 d2,d2 +vmlal.s32 q4,d26,d19 +vext.32 d3,d5,d15,#1 +vmlal.s32 q4,d27,d18 +vrev64.i32 d3,d3 +vmlal.s32 q4,d28,d15 +vext.32 d14,d12,d11,#1 +vmull.s32 q5,d16,d23 +vext.32 d15,d13,d12,#1 +vmlal.s32 q5,d17,d4 +vst1.8 d8,[r5,: 64]! +vmlal.s32 q5,d14,d1 +vext.32 d12,d9,d8,#0 +vmlal.s32 q5,d15,d19 +vmov.i64 d13,#0 +vmlal.s32 q5,d29,d18 +vext.32 d25,d19,d7,#1 +vmlal.s32 q6,d20,d5 +vrev64.i32 d25,d25 +vmlal.s32 q6,d21,d4 +vst1.8 d11,[r5,: 64]! +vmlal.s32 q6,d26,d1 +vext.32 d9,d10,d10,#0 +vmlal.s32 q6,d27,d19 +vmov.i64 d8,#0 +vmlal.s32 q6,d28,d18 +vmlal.s32 q4,d16,d24 +vmlal.s32 q4,d17,d5 +vmlal.s32 q4,d14,d4 +vst1.8 d12,[r5,: 64]! +vmlal.s32 q4,d15,d1 +vext.32 d10,d13,d12,#0 +vmlal.s32 q4,d29,d19 +vmov.i64 d11,#0 +vmlal.s32 q5,d20,d6 +vmlal.s32 q5,d21,d5 +vmlal.s32 q5,d26,d4 +vext.32 d13,d8,d8,#0 +vmlal.s32 q5,d27,d1 +vmov.i64 d12,#0 +vmlal.s32 q5,d28,d19 +vst1.8 d9,[r5,: 64]! +vmlal.s32 q6,d16,d25 +vmlal.s32 q6,d17,d6 +vst1.8 d10,[r5,: 64] +vmlal.s32 q6,d14,d5 +vext.32 d8,d11,d10,#0 +vmlal.s32 q6,d15,d4 +vmov.i64 d9,#0 +vmlal.s32 q6,d29,d1 +vmlal.s32 q4,d20,d7 +vmlal.s32 q4,d21,d6 +vmlal.s32 q4,d26,d5 +vext.32 d11,d12,d12,#0 +vmlal.s32 q4,d27,d4 +vmov.i64 d10,#0 +vmlal.s32 q4,d28,d1 +vmlal.s32 q5,d16,d0 +sub r2,r5,#32 +vmlal.s32 q5,d17,d7 +vmlal.s32 q5,d14,d6 +vext.32 d30,d9,d8,#0 +vmlal.s32 q5,d15,d5 +vld1.8 {d31},[r2,: 64]! +vmlal.s32 q5,d29,d4 +vmlal.s32 q15,d20,d0 +vext.32 d0,d6,d18,#1 +vmlal.s32 q15,d21,d25 +vrev64.i32 d0,d0 +vmlal.s32 q15,d26,d24 +vext.32 d1,d7,d19,#1 +vext.32 d7,d10,d10,#0 +vmlal.s32 q15,d27,d23 +vrev64.i32 d1,d1 +vld1.8 {d6},[r2,: 64] +vmlal.s32 q15,d28,d22 +vmlal.s32 q3,d16,d4 +add r2,r2,#24 +vmlal.s32 q3,d17,d2 +vext.32 d4,d31,d30,#0 +vmov d17,d11 +vmlal.s32 q3,d14,d1 +vext.32 d11,d13,d13,#0 +vext.32 d13,d30,d30,#0 +vmlal.s32 q3,d15,d0 +vext.32 d1,d8,d8,#0 +vmlal.s32 q3,d29,d3 +vld1.8 {d5},[r2,: 64] +sub r2,r2,#16 +vext.32 d10,d6,d6,#0 +vmov.i32 q1,#0xffffffff +vshl.i64 q4,q1,#25 +add r5,sp,#512 +vld1.8 {d14-d15},[r5,: 128] +vadd.i64 q9,q2,q7 +vshl.i64 q1,q1,#26 +vshr.s64 q10,q9,#26 +vld1.8 {d0},[r2,: 64]! +vadd.i64 q5,q5,q10 +vand q9,q9,q1 +vld1.8 {d16},[r2,: 64]! +add r2,sp,#528 +vld1.8 {d20-d21},[r2,: 128] +vadd.i64 q11,q5,q10 +vsub.i64 q2,q2,q9 +vshr.s64 q9,q11,#25 +vext.32 d12,d5,d4,#0 +vand q11,q11,q4 +vadd.i64 q0,q0,q9 +vmov d19,d7 +vadd.i64 q3,q0,q7 +vsub.i64 q5,q5,q11 +vshr.s64 q11,q3,#26 +vext.32 d18,d11,d10,#0 +vand q3,q3,q1 +vadd.i64 q8,q8,q11 +vadd.i64 q11,q8,q10 +vsub.i64 q0,q0,q3 +vshr.s64 q3,q11,#25 +vand q11,q11,q4 +vadd.i64 q3,q6,q3 +vadd.i64 q6,q3,q7 +vsub.i64 q8,q8,q11 +vshr.s64 q11,q6,#26 +vand q6,q6,q1 +vadd.i64 q9,q9,q11 +vadd.i64 d25,d19,d21 +vsub.i64 q3,q3,q6 +vshr.s64 d23,d25,#25 +vand q4,q12,q4 +vadd.i64 d21,d23,d23 +vshl.i64 d25,d23,#4 +vadd.i64 d21,d21,d23 +vadd.i64 d25,d25,d21 +vadd.i64 d4,d4,d25 +vzip.i32 q0,q8 +vadd.i64 d12,d4,d14 +add r2,r6,#8 +vst1.8 d0,[r2,: 64] +vsub.i64 d19,d19,d9 +add r2,r2,#16 +vst1.8 d16,[r2,: 64] +vshr.s64 d22,d12,#26 +vand q0,q6,q1 +vadd.i64 d10,d10,d22 +vzip.i32 q3,q9 +vsub.i64 d4,d4,d0 +sub r2,r2,#8 +vst1.8 d6,[r2,: 64] +add r2,r2,#16 +vst1.8 d18,[r2,: 64] +vzip.i32 q2,q5 +sub r2,r2,#32 +vst1.8 d4,[r2,: 64] +cmp r4,#0 +beq ._skippostcopy +add r2,r3,#144 +mov r4,r4 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4},[r2,: 64] +vst1.8 {d0-d1},[r4,: 128]! +vst1.8 {d2-d3},[r4,: 128]! +vst1.8 d4,[r4,: 64] +._skippostcopy: +cmp r1,#1 +bne ._skipfinalcopy +add r2,r3,#288 +add r4,r3,#144 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4},[r2,: 64] +vst1.8 {d0-d1},[r4,: 128]! +vst1.8 {d2-d3},[r4,: 128]! +vst1.8 d4,[r4,: 64] +._skipfinalcopy: +add r1,r1,#1 +cmp r1,#12 +blo ._invertloop +add r1,r3,#144 +ldr r2,[r1],#4 +ldr r3,[r1],#4 +ldr r4,[r1],#4 +ldr r5,[r1],#4 +ldr r6,[r1],#4 +ldr r7,[r1],#4 +ldr r8,[r1],#4 +ldr r9,[r1],#4 +ldr r10,[r1],#4 +ldr r1,[r1] +add r11,r1,r1,LSL #4 +add r11,r11,r1,LSL #1 +add r11,r11,#16777216 +mov r11,r11,ASR #25 +add r11,r11,r2 +mov r11,r11,ASR #26 +add r11,r11,r3 +mov r11,r11,ASR #25 +add r11,r11,r4 +mov r11,r11,ASR #26 +add r11,r11,r5 +mov r11,r11,ASR #25 +add r11,r11,r6 +mov r11,r11,ASR #26 +add r11,r11,r7 +mov r11,r11,ASR #25 +add r11,r11,r8 +mov r11,r11,ASR #26 +add r11,r11,r9 +mov r11,r11,ASR #25 +add r11,r11,r10 +mov r11,r11,ASR #26 +add r11,r11,r1 +mov r11,r11,ASR #25 +add r2,r2,r11 +add r2,r2,r11,LSL #1 +add r2,r2,r11,LSL #4 +mov r11,r2,ASR #26 +add r3,r3,r11 +sub r2,r2,r11,LSL #26 +mov r11,r3,ASR #25 +add r4,r4,r11 +sub r3,r3,r11,LSL #25 +mov r11,r4,ASR #26 +add r5,r5,r11 +sub r4,r4,r11,LSL #26 +mov r11,r5,ASR #25 +add r6,r6,r11 +sub r5,r5,r11,LSL #25 +mov r11,r6,ASR #26 +add r7,r7,r11 +sub r6,r6,r11,LSL #26 +mov r11,r7,ASR #25 +add r8,r8,r11 +sub r7,r7,r11,LSL #25 +mov r11,r8,ASR #26 +add r9,r9,r11 +sub r8,r8,r11,LSL #26 +mov r11,r9,ASR #25 +add r10,r10,r11 +sub r9,r9,r11,LSL #25 +mov r11,r10,ASR #26 +add r1,r1,r11 +sub r10,r10,r11,LSL #26 +mov r11,r1,ASR #25 +sub r1,r1,r11,LSL #25 +add r2,r2,r3,LSL #26 +mov r3,r3,LSR #6 +add r3,r3,r4,LSL #19 +mov r4,r4,LSR #13 +add r4,r4,r5,LSL #13 +mov r5,r5,LSR #19 +add r5,r5,r6,LSL #6 +add r6,r7,r8,LSL #25 +mov r7,r8,LSR #7 +add r7,r7,r9,LSL #19 +mov r8,r9,LSR #13 +add r8,r8,r10,LSL #12 +mov r9,r10,LSR #20 +add r1,r9,r1,LSL #6 +str r2,[r0],#4 +str r3,[r0],#4 +str r4,[r0],#4 +str r5,[r0],#4 +str r6,[r0],#4 +str r7,[r0],#4 +str r8,[r0],#4 +str r1,[r0] +ldrd r4,[sp,#0] +ldrd r6,[sp,#8] +ldrd r8,[sp,#16] +ldrd r10,[sp,#24] +ldr r12,[sp,#480] +ldr r14,[sp,#484] +ldr r0,=0 +mov sp,r12 +vpop {q4,q5,q6,q7} +bx lr + +#endif /* __arm__ */ +#endif /* !OPENSSL_NO_ASM */ diff --git a/external/boringssl/crypto/curve25519/asm/x25519-asm-x86_64.S b/external/boringssl/crypto/curve25519/asm/x25519-asm-x86_64.S new file mode 100644 index 0000000000..531ac16332 --- /dev/null +++ b/external/boringssl/crypto/curve25519/asm/x25519-asm-x86_64.S @@ -0,0 +1,1937 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This file is adapted from crypto_scalarmult/curve25519/amd64-51/ in + * SUPERCOP 20141124 (http://bench.cr.yp.to/supercop.html). That code is public + * domain licensed but the standard ISC license is included above to keep + * licensing simple. */ + +#if !defined(OPENSSL_NO_ASM) +#if defined(__x86_64__) + +.data +.p2align 4 + +#if defined(__APPLE__) +/* OS X's C ABI prefixes functions with underscore. */ +#define C_ABI(x) _ ## x +#define HIDDEN .private_extern +#else +#define C_ABI(x) x +#define HIDDEN .hidden +#endif + +x25519_x86_64_REDMASK51: .quad 0x0007FFFFFFFFFFFF +x25519_x86_64_121666_213: .quad 996687872 +x25519_x86_64_2P0: .quad 0xFFFFFFFFFFFDA +x25519_x86_64_2P1234: .quad 0xFFFFFFFFFFFFE +x25519_x86_64_4P0: .quad 0x1FFFFFFFFFFFB4 +x25519_x86_64_4P1234: .quad 0x1FFFFFFFFFFFFC +x25519_x86_64_MU0: .quad 0xED9CE5A30A2C131B +x25519_x86_64_MU1: .quad 0x2106215D086329A7 +x25519_x86_64_MU2: .quad 0xFFFFFFFFFFFFFFEB +x25519_x86_64_MU3: .quad 0xFFFFFFFFFFFFFFFF +x25519_x86_64_MU4: .quad 0x000000000000000F +x25519_x86_64_ORDER0: .quad 0x5812631A5CF5D3ED +x25519_x86_64_ORDER1: .quad 0x14DEF9DEA2F79CD6 +x25519_x86_64_ORDER2: .quad 0x0000000000000000 +x25519_x86_64_ORDER3: .quad 0x1000000000000000 +x25519_x86_64_EC2D0: .quad 1859910466990425 +x25519_x86_64_EC2D1: .quad 932731440258426 +x25519_x86_64_EC2D2: .quad 1072319116312658 +x25519_x86_64_EC2D3: .quad 1815898335770999 +x25519_x86_64_EC2D4: .quad 633789495995903 +x25519_x86_64__38: .quad 38 + +.text +.p2align 5 + +.globl C_ABI(x25519_x86_64_freeze) +HIDDEN C_ABI(x25519_x86_64_freeze) +C_ABI(x25519_x86_64_freeze): +mov %rsp,%r11 +and $31,%r11 +add $64,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq 0(%rdi),%rsi +movq 8(%rdi),%rdx +movq 16(%rdi),%rcx +movq 24(%rdi),%r8 +movq 32(%rdi),%r9 +movq x25519_x86_64_REDMASK51(%rip),%rax +mov %rax,%r10 +sub $18,%r10 +mov $3,%r11 +._reduceloop: +mov %rsi,%r12 +shr $51,%r12 +and %rax,%rsi +add %r12,%rdx +mov %rdx,%r12 +shr $51,%r12 +and %rax,%rdx +add %r12,%rcx +mov %rcx,%r12 +shr $51,%r12 +and %rax,%rcx +add %r12,%r8 +mov %r8,%r12 +shr $51,%r12 +and %rax,%r8 +add %r12,%r9 +mov %r9,%r12 +shr $51,%r12 +and %rax,%r9 +imulq $19,%r12,%r12 +add %r12,%rsi +sub $1,%r11 +ja ._reduceloop +mov $1,%r12 +cmp %r10,%rsi +cmovl %r11,%r12 +cmp %rax,%rdx +cmovne %r11,%r12 +cmp %rax,%rcx +cmovne %r11,%r12 +cmp %rax,%r8 +cmovne %r11,%r12 +cmp %rax,%r9 +cmovne %r11,%r12 +neg %r12 +and %r12,%rax +and %r12,%r10 +sub %r10,%rsi +sub %rax,%rdx +sub %rax,%rcx +sub %rax,%r8 +sub %rax,%r9 +movq %rsi,0(%rdi) +movq %rdx,8(%rdi) +movq %rcx,16(%rdi) +movq %r8,24(%rdi) +movq %r9,32(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_mul) +HIDDEN C_ABI(x25519_x86_64_mul) +C_ABI(x25519_x86_64_mul): +mov %rsp,%r11 +and $31,%r11 +add $96,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq %rdi,56(%rsp) +mov %rdx,%rcx +movq 24(%rsi),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 16(%rcx) +mov %rax,%r8 +mov %rdx,%r9 +movq 32(%rsi),%rdx +imulq $19,%rdx,%rax +movq %rax,72(%rsp) +mulq 8(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 0(%rsi),%rax +mulq 0(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 0(%rsi),%rax +mulq 8(%rcx) +mov %rax,%r10 +mov %rdx,%r11 +movq 0(%rsi),%rax +mulq 16(%rcx) +mov %rax,%r12 +mov %rdx,%r13 +movq 0(%rsi),%rax +mulq 24(%rcx) +mov %rax,%r14 +mov %rdx,%r15 +movq 0(%rsi),%rax +mulq 32(%rcx) +mov %rax,%rbx +mov %rdx,%rbp +movq 8(%rsi),%rax +mulq 0(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 8(%rsi),%rax +mulq 8(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 8(%rsi),%rax +mulq 16(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq 8(%rsi),%rax +mulq 24(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 8(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 16(%rsi),%rax +mulq 0(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 16(%rsi),%rax +mulq 8(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq 16(%rsi),%rax +mulq 16(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 16(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 24(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 16(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 24(%rsi),%rax +mulq 0(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq 24(%rsi),%rax +mulq 8(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 64(%rsp),%rax +mulq 24(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 32(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 32(%rsi),%rax +mulq 0(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 72(%rsp),%rax +mulq 16(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 72(%rsp),%rax +mulq 24(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 72(%rsp),%rax +mulq 32(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq x25519_x86_64_REDMASK51(%rip),%rsi +shld $13,%r8,%r9 +and %rsi,%r8 +shld $13,%r10,%r11 +and %rsi,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rsi,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rsi,%r14 +add %r13,%r14 +shld $13,%rbx,%rbp +and %rsi,%rbx +add %r15,%rbx +imulq $19,%rbp,%rdx +add %rdx,%r8 +mov %r8,%rdx +shr $51,%rdx +add %r10,%rdx +mov %rdx,%rcx +shr $51,%rdx +and %rsi,%r8 +add %r12,%rdx +mov %rdx,%r9 +shr $51,%rdx +and %rsi,%rcx +add %r14,%rdx +mov %rdx,%rax +shr $51,%rdx +and %rsi,%r9 +add %rbx,%rdx +mov %rdx,%r10 +shr $51,%rdx +and %rsi,%rax +imulq $19,%rdx,%rdx +add %rdx,%r8 +and %rsi,%r10 +movq %r8,0(%rdi) +movq %rcx,8(%rdi) +movq %r9,16(%rdi) +movq %rax,24(%rdi) +movq %r10,32(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_square) +HIDDEN C_ABI(x25519_x86_64_square) +C_ABI(x25519_x86_64_square): +mov %rsp,%r11 +and $31,%r11 +add $64,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq 0(%rsi),%rax +mulq 0(%rsi) +mov %rax,%rcx +mov %rdx,%r8 +movq 0(%rsi),%rax +shl $1,%rax +mulq 8(%rsi) +mov %rax,%r9 +mov %rdx,%r10 +movq 0(%rsi),%rax +shl $1,%rax +mulq 16(%rsi) +mov %rax,%r11 +mov %rdx,%r12 +movq 0(%rsi),%rax +shl $1,%rax +mulq 24(%rsi) +mov %rax,%r13 +mov %rdx,%r14 +movq 0(%rsi),%rax +shl $1,%rax +mulq 32(%rsi) +mov %rax,%r15 +mov %rdx,%rbx +movq 8(%rsi),%rax +mulq 8(%rsi) +add %rax,%r11 +adc %rdx,%r12 +movq 8(%rsi),%rax +shl $1,%rax +mulq 16(%rsi) +add %rax,%r13 +adc %rdx,%r14 +movq 8(%rsi),%rax +shl $1,%rax +mulq 24(%rsi) +add %rax,%r15 +adc %rdx,%rbx +movq 8(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 32(%rsi) +add %rax,%rcx +adc %rdx,%r8 +movq 16(%rsi),%rax +mulq 16(%rsi) +add %rax,%r15 +adc %rdx,%rbx +movq 16(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 24(%rsi) +add %rax,%rcx +adc %rdx,%r8 +movq 16(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 32(%rsi) +add %rax,%r9 +adc %rdx,%r10 +movq 24(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 24(%rsi) +add %rax,%r9 +adc %rdx,%r10 +movq 24(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 32(%rsi) +add %rax,%r11 +adc %rdx,%r12 +movq 32(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rsi) +add %rax,%r13 +adc %rdx,%r14 +movq x25519_x86_64_REDMASK51(%rip),%rsi +shld $13,%rcx,%r8 +and %rsi,%rcx +shld $13,%r9,%r10 +and %rsi,%r9 +add %r8,%r9 +shld $13,%r11,%r12 +and %rsi,%r11 +add %r10,%r11 +shld $13,%r13,%r14 +and %rsi,%r13 +add %r12,%r13 +shld $13,%r15,%rbx +and %rsi,%r15 +add %r14,%r15 +imulq $19,%rbx,%rdx +add %rdx,%rcx +mov %rcx,%rdx +shr $51,%rdx +add %r9,%rdx +and %rsi,%rcx +mov %rdx,%r8 +shr $51,%rdx +add %r11,%rdx +and %rsi,%r8 +mov %rdx,%r9 +shr $51,%rdx +add %r13,%rdx +and %rsi,%r9 +mov %rdx,%rax +shr $51,%rdx +add %r15,%rdx +and %rsi,%rax +mov %rdx,%r10 +shr $51,%rdx +imulq $19,%rdx,%rdx +add %rdx,%rcx +and %rsi,%r10 +movq %rcx,0(%rdi) +movq %r8,8(%rdi) +movq %r9,16(%rdi) +movq %rax,24(%rdi) +movq %r10,32(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_ladderstep) +HIDDEN C_ABI(x25519_x86_64_ladderstep) +C_ABI(x25519_x86_64_ladderstep): +mov %rsp,%r11 +and $31,%r11 +add $352,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq 40(%rdi),%rsi +movq 48(%rdi),%rdx +movq 56(%rdi),%rcx +movq 64(%rdi),%r8 +movq 72(%rdi),%r9 +mov %rsi,%rax +mov %rdx,%r10 +mov %rcx,%r11 +mov %r8,%r12 +mov %r9,%r13 +add x25519_x86_64_2P0(%rip),%rax +add x25519_x86_64_2P1234(%rip),%r10 +add x25519_x86_64_2P1234(%rip),%r11 +add x25519_x86_64_2P1234(%rip),%r12 +add x25519_x86_64_2P1234(%rip),%r13 +addq 80(%rdi),%rsi +addq 88(%rdi),%rdx +addq 96(%rdi),%rcx +addq 104(%rdi),%r8 +addq 112(%rdi),%r9 +subq 80(%rdi),%rax +subq 88(%rdi),%r10 +subq 96(%rdi),%r11 +subq 104(%rdi),%r12 +subq 112(%rdi),%r13 +movq %rsi,56(%rsp) +movq %rdx,64(%rsp) +movq %rcx,72(%rsp) +movq %r8,80(%rsp) +movq %r9,88(%rsp) +movq %rax,96(%rsp) +movq %r10,104(%rsp) +movq %r11,112(%rsp) +movq %r12,120(%rsp) +movq %r13,128(%rsp) +movq 96(%rsp),%rax +mulq 96(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 96(%rsp),%rax +shl $1,%rax +mulq 104(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 96(%rsp),%rax +shl $1,%rax +mulq 112(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 96(%rsp),%rax +shl $1,%rax +mulq 120(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 96(%rsp),%rax +shl $1,%rax +mulq 128(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 104(%rsp),%rax +mulq 104(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 104(%rsp),%rax +shl $1,%rax +mulq 112(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 104(%rsp),%rax +shl $1,%rax +mulq 120(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 104(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 128(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 112(%rsp),%rax +mulq 112(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 112(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 120(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 112(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 128(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 120(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 120(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 120(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 128(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 128(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 128(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,136(%rsp) +movq %r8,144(%rsp) +movq %r9,152(%rsp) +movq %rax,160(%rsp) +movq %r10,168(%rsp) +movq 56(%rsp),%rax +mulq 56(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 56(%rsp),%rax +shl $1,%rax +mulq 64(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 56(%rsp),%rax +shl $1,%rax +mulq 72(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 56(%rsp),%rax +shl $1,%rax +mulq 80(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 56(%rsp),%rax +shl $1,%rax +mulq 88(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 64(%rsp),%rax +mulq 64(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +shl $1,%rax +mulq 72(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 64(%rsp),%rax +shl $1,%rax +mulq 80(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 88(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 72(%rsp),%rax +mulq 72(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 72(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 80(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 72(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 88(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 80(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 80(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 80(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 88(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 88(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 88(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,176(%rsp) +movq %r8,184(%rsp) +movq %r9,192(%rsp) +movq %rax,200(%rsp) +movq %r10,208(%rsp) +mov %rsi,%rsi +mov %r8,%rdx +mov %r9,%rcx +mov %rax,%r8 +mov %r10,%r9 +add x25519_x86_64_2P0(%rip),%rsi +add x25519_x86_64_2P1234(%rip),%rdx +add x25519_x86_64_2P1234(%rip),%rcx +add x25519_x86_64_2P1234(%rip),%r8 +add x25519_x86_64_2P1234(%rip),%r9 +subq 136(%rsp),%rsi +subq 144(%rsp),%rdx +subq 152(%rsp),%rcx +subq 160(%rsp),%r8 +subq 168(%rsp),%r9 +movq %rsi,216(%rsp) +movq %rdx,224(%rsp) +movq %rcx,232(%rsp) +movq %r8,240(%rsp) +movq %r9,248(%rsp) +movq 120(%rdi),%rsi +movq 128(%rdi),%rdx +movq 136(%rdi),%rcx +movq 144(%rdi),%r8 +movq 152(%rdi),%r9 +mov %rsi,%rax +mov %rdx,%r10 +mov %rcx,%r11 +mov %r8,%r12 +mov %r9,%r13 +add x25519_x86_64_2P0(%rip),%rax +add x25519_x86_64_2P1234(%rip),%r10 +add x25519_x86_64_2P1234(%rip),%r11 +add x25519_x86_64_2P1234(%rip),%r12 +add x25519_x86_64_2P1234(%rip),%r13 +addq 160(%rdi),%rsi +addq 168(%rdi),%rdx +addq 176(%rdi),%rcx +addq 184(%rdi),%r8 +addq 192(%rdi),%r9 +subq 160(%rdi),%rax +subq 168(%rdi),%r10 +subq 176(%rdi),%r11 +subq 184(%rdi),%r12 +subq 192(%rdi),%r13 +movq %rsi,256(%rsp) +movq %rdx,264(%rsp) +movq %rcx,272(%rsp) +movq %r8,280(%rsp) +movq %r9,288(%rsp) +movq %rax,296(%rsp) +movq %r10,304(%rsp) +movq %r11,312(%rsp) +movq %r12,320(%rsp) +movq %r13,328(%rsp) +movq 280(%rsp),%rsi +imulq $19,%rsi,%rax +movq %rax,336(%rsp) +mulq 112(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 288(%rsp),%rdx +imulq $19,%rdx,%rax +movq %rax,344(%rsp) +mulq 104(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 256(%rsp),%rax +mulq 96(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 256(%rsp),%rax +mulq 104(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 256(%rsp),%rax +mulq 112(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 256(%rsp),%rax +mulq 120(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 256(%rsp),%rax +mulq 128(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 264(%rsp),%rax +mulq 96(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 264(%rsp),%rax +mulq 104(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 264(%rsp),%rax +mulq 112(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 264(%rsp),%rax +mulq 120(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 264(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 128(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 272(%rsp),%rax +mulq 96(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 272(%rsp),%rax +mulq 104(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 272(%rsp),%rax +mulq 112(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 272(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 120(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 272(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 128(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 280(%rsp),%rax +mulq 96(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 280(%rsp),%rax +mulq 104(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 336(%rsp),%rax +mulq 120(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 336(%rsp),%rax +mulq 128(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 288(%rsp),%rax +mulq 96(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 344(%rsp),%rax +mulq 112(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 344(%rsp),%rax +mulq 120(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 344(%rsp),%rax +mulq 128(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,96(%rsp) +movq %r8,104(%rsp) +movq %r9,112(%rsp) +movq %rax,120(%rsp) +movq %r10,128(%rsp) +movq 320(%rsp),%rsi +imulq $19,%rsi,%rax +movq %rax,256(%rsp) +mulq 72(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 328(%rsp),%rdx +imulq $19,%rdx,%rax +movq %rax,264(%rsp) +mulq 64(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 296(%rsp),%rax +mulq 56(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 296(%rsp),%rax +mulq 64(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 296(%rsp),%rax +mulq 72(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 296(%rsp),%rax +mulq 80(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 296(%rsp),%rax +mulq 88(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 304(%rsp),%rax +mulq 56(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 304(%rsp),%rax +mulq 64(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 304(%rsp),%rax +mulq 72(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 304(%rsp),%rax +mulq 80(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 304(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 88(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 312(%rsp),%rax +mulq 56(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 312(%rsp),%rax +mulq 64(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 312(%rsp),%rax +mulq 72(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 312(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 80(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 312(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 88(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 320(%rsp),%rax +mulq 56(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 320(%rsp),%rax +mulq 64(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 256(%rsp),%rax +mulq 80(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 256(%rsp),%rax +mulq 88(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 328(%rsp),%rax +mulq 56(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 264(%rsp),%rax +mulq 72(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 264(%rsp),%rax +mulq 80(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 264(%rsp),%rax +mulq 88(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +mov %rsi,%rdx +mov %r8,%rcx +mov %r9,%r11 +mov %rax,%r12 +mov %r10,%r13 +add x25519_x86_64_2P0(%rip),%rdx +add x25519_x86_64_2P1234(%rip),%rcx +add x25519_x86_64_2P1234(%rip),%r11 +add x25519_x86_64_2P1234(%rip),%r12 +add x25519_x86_64_2P1234(%rip),%r13 +addq 96(%rsp),%rsi +addq 104(%rsp),%r8 +addq 112(%rsp),%r9 +addq 120(%rsp),%rax +addq 128(%rsp),%r10 +subq 96(%rsp),%rdx +subq 104(%rsp),%rcx +subq 112(%rsp),%r11 +subq 120(%rsp),%r12 +subq 128(%rsp),%r13 +movq %rsi,120(%rdi) +movq %r8,128(%rdi) +movq %r9,136(%rdi) +movq %rax,144(%rdi) +movq %r10,152(%rdi) +movq %rdx,160(%rdi) +movq %rcx,168(%rdi) +movq %r11,176(%rdi) +movq %r12,184(%rdi) +movq %r13,192(%rdi) +movq 120(%rdi),%rax +mulq 120(%rdi) +mov %rax,%rsi +mov %rdx,%rcx +movq 120(%rdi),%rax +shl $1,%rax +mulq 128(%rdi) +mov %rax,%r8 +mov %rdx,%r9 +movq 120(%rdi),%rax +shl $1,%rax +mulq 136(%rdi) +mov %rax,%r10 +mov %rdx,%r11 +movq 120(%rdi),%rax +shl $1,%rax +mulq 144(%rdi) +mov %rax,%r12 +mov %rdx,%r13 +movq 120(%rdi),%rax +shl $1,%rax +mulq 152(%rdi) +mov %rax,%r14 +mov %rdx,%r15 +movq 128(%rdi),%rax +mulq 128(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 128(%rdi),%rax +shl $1,%rax +mulq 136(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 128(%rdi),%rax +shl $1,%rax +mulq 144(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 128(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 152(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 136(%rdi),%rax +mulq 136(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 136(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 144(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 136(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 152(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 144(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 144(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 144(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 152(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 152(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 152(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,120(%rdi) +movq %r8,128(%rdi) +movq %r9,136(%rdi) +movq %rax,144(%rdi) +movq %r10,152(%rdi) +movq 160(%rdi),%rax +mulq 160(%rdi) +mov %rax,%rsi +mov %rdx,%rcx +movq 160(%rdi),%rax +shl $1,%rax +mulq 168(%rdi) +mov %rax,%r8 +mov %rdx,%r9 +movq 160(%rdi),%rax +shl $1,%rax +mulq 176(%rdi) +mov %rax,%r10 +mov %rdx,%r11 +movq 160(%rdi),%rax +shl $1,%rax +mulq 184(%rdi) +mov %rax,%r12 +mov %rdx,%r13 +movq 160(%rdi),%rax +shl $1,%rax +mulq 192(%rdi) +mov %rax,%r14 +mov %rdx,%r15 +movq 168(%rdi),%rax +mulq 168(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 168(%rdi),%rax +shl $1,%rax +mulq 176(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 168(%rdi),%rax +shl $1,%rax +mulq 184(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 168(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 192(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rax +mulq 176(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 176(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 184(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 192(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 184(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 192(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 192(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 192(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,160(%rdi) +movq %r8,168(%rdi) +movq %r9,176(%rdi) +movq %rax,184(%rdi) +movq %r10,192(%rdi) +movq 184(%rdi),%rsi +imulq $19,%rsi,%rax +movq %rax,56(%rsp) +mulq 16(%rdi) +mov %rax,%rsi +mov %rdx,%rcx +movq 192(%rdi),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 8(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 160(%rdi),%rax +mulq 0(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 160(%rdi),%rax +mulq 8(%rdi) +mov %rax,%r8 +mov %rdx,%r9 +movq 160(%rdi),%rax +mulq 16(%rdi) +mov %rax,%r10 +mov %rdx,%r11 +movq 160(%rdi),%rax +mulq 24(%rdi) +mov %rax,%r12 +mov %rdx,%r13 +movq 160(%rdi),%rax +mulq 32(%rdi) +mov %rax,%r14 +mov %rdx,%r15 +movq 168(%rdi),%rax +mulq 0(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 168(%rdi),%rax +mulq 8(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 168(%rdi),%rax +mulq 16(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 168(%rdi),%rax +mulq 24(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 168(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rax +mulq 0(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 176(%rdi),%rax +mulq 8(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 176(%rdi),%rax +mulq 16(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 176(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 24(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rdi),%rax +mulq 0(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 184(%rdi),%rax +mulq 8(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 56(%rsp),%rax +mulq 24(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 56(%rsp),%rax +mulq 32(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 192(%rdi),%rax +mulq 0(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rax +mulq 16(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 64(%rsp),%rax +mulq 24(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 32(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,160(%rdi) +movq %r8,168(%rdi) +movq %r9,176(%rdi) +movq %rax,184(%rdi) +movq %r10,192(%rdi) +movq 200(%rsp),%rsi +imulq $19,%rsi,%rax +movq %rax,56(%rsp) +mulq 152(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 208(%rsp),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 144(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rsp),%rax +mulq 136(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rsp),%rax +mulq 144(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 176(%rsp),%rax +mulq 152(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 176(%rsp),%rax +mulq 160(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 176(%rsp),%rax +mulq 168(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 184(%rsp),%rax +mulq 136(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rsp),%rax +mulq 144(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 184(%rsp),%rax +mulq 152(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 184(%rsp),%rax +mulq 160(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 184(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 168(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 192(%rsp),%rax +mulq 136(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 192(%rsp),%rax +mulq 144(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 192(%rsp),%rax +mulq 152(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 192(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 160(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 192(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 168(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 200(%rsp),%rax +mulq 136(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 200(%rsp),%rax +mulq 144(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 56(%rsp),%rax +mulq 160(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 56(%rsp),%rax +mulq 168(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 208(%rsp),%rax +mulq 136(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rax +mulq 152(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 64(%rsp),%rax +mulq 160(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 168(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,40(%rdi) +movq %r8,48(%rdi) +movq %r9,56(%rdi) +movq %rax,64(%rdi) +movq %r10,72(%rdi) +movq 216(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +mov %rax,%rsi +mov %rdx,%rcx +movq 224(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%rcx +mov %rdx,%r8 +movq 232(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%r8 +mov %rdx,%r9 +movq 240(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%r9 +mov %rdx,%r10 +movq 248(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%r10 +imulq $19,%rdx,%rdx +add %rdx,%rsi +addq 136(%rsp),%rsi +addq 144(%rsp),%rcx +addq 152(%rsp),%r8 +addq 160(%rsp),%r9 +addq 168(%rsp),%r10 +movq %rsi,80(%rdi) +movq %rcx,88(%rdi) +movq %r8,96(%rdi) +movq %r9,104(%rdi) +movq %r10,112(%rdi) +movq 104(%rdi),%rsi +imulq $19,%rsi,%rax +movq %rax,56(%rsp) +mulq 232(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 112(%rdi),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 224(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 80(%rdi),%rax +mulq 216(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 80(%rdi),%rax +mulq 224(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 80(%rdi),%rax +mulq 232(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 80(%rdi),%rax +mulq 240(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 80(%rdi),%rax +mulq 248(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 88(%rdi),%rax +mulq 216(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 88(%rdi),%rax +mulq 224(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 88(%rdi),%rax +mulq 232(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 88(%rdi),%rax +mulq 240(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 88(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 248(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 96(%rdi),%rax +mulq 216(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 96(%rdi),%rax +mulq 224(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 96(%rdi),%rax +mulq 232(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 96(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 240(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 96(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 248(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 104(%rdi),%rax +mulq 216(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 104(%rdi),%rax +mulq 224(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 56(%rsp),%rax +mulq 240(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 56(%rsp),%rax +mulq 248(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 112(%rdi),%rax +mulq 216(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rax +mulq 232(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 64(%rsp),%rax +mulq 240(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 248(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,80(%rdi) +movq %r8,88(%rdi) +movq %r9,96(%rdi) +movq %rax,104(%rdi) +movq %r10,112(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_work_cswap) +HIDDEN C_ABI(x25519_x86_64_work_cswap) +C_ABI(x25519_x86_64_work_cswap): +mov %rsp,%r11 +and $31,%r11 +add $0,%r11 +sub %r11,%rsp +cmp $1,%rsi +movq 0(%rdi),%rsi +movq 80(%rdi),%rdx +movq 8(%rdi),%rcx +movq 88(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,0(%rdi) +movq %rdx,80(%rdi) +movq %rcx,8(%rdi) +movq %r8,88(%rdi) +movq 16(%rdi),%rsi +movq 96(%rdi),%rdx +movq 24(%rdi),%rcx +movq 104(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,16(%rdi) +movq %rdx,96(%rdi) +movq %rcx,24(%rdi) +movq %r8,104(%rdi) +movq 32(%rdi),%rsi +movq 112(%rdi),%rdx +movq 40(%rdi),%rcx +movq 120(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,32(%rdi) +movq %rdx,112(%rdi) +movq %rcx,40(%rdi) +movq %r8,120(%rdi) +movq 48(%rdi),%rsi +movq 128(%rdi),%rdx +movq 56(%rdi),%rcx +movq 136(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,48(%rdi) +movq %rdx,128(%rdi) +movq %rcx,56(%rdi) +movq %r8,136(%rdi) +movq 64(%rdi),%rsi +movq 144(%rdi),%rdx +movq 72(%rdi),%rcx +movq 152(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,64(%rdi) +movq %rdx,144(%rdi) +movq %rcx,72(%rdi) +movq %r8,152(%rdi) +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +#endif /* __x86_64__ */ +#endif /* !OPENSSL_NO_ASM */ diff --git a/external/boringssl/crypto/curve25519/curve25519.c.REMOVED.git-id b/external/boringssl/crypto/curve25519/curve25519.c.REMOVED.git-id new file mode 100644 index 0000000000..c14695bfbd --- /dev/null +++ b/external/boringssl/crypto/curve25519/curve25519.c.REMOVED.git-id @@ -0,0 +1 @@ +1dd1b3ed76d4f6a8770552896cf254bbdbe9cb6b \ No newline at end of file diff --git a/external/boringssl/crypto/curve25519/ed25519_test.cc b/external/boringssl/crypto/curve25519/ed25519_test.cc new file mode 100644 index 0000000000..1b6a0b6157 --- /dev/null +++ b/external/boringssl/crypto/curve25519/ed25519_test.cc @@ -0,0 +1,63 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include + +#include "../test/file_test.h" + + +static bool TestSignature(FileTest *t, void *arg) { + std::vector private_key, public_key, message, expected_signature; + if (!t->GetBytes(&private_key, "PRIV") || + private_key.size() != 64 || + !t->GetBytes(&public_key, "PUB") || + public_key.size() != 32 || + !t->GetBytes(&message, "MESSAGE") || + !t->GetBytes(&expected_signature, "SIG") || + expected_signature.size() != 64) { + return false; + } + + uint8_t signature[64]; + if (!ED25519_sign(signature, message.data(), message.size(), + private_key.data())) { + t->PrintLine("ED25519_sign failed"); + return false; + } + + if (!t->ExpectBytesEqual(expected_signature.data(), expected_signature.size(), + signature, sizeof(signature))) { + return false; + } + + if (!ED25519_verify(message.data(), message.size(), signature, + public_key.data())) { + t->PrintLine("ED25519_verify failed"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestSignature, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/curve25519/ed25519_tests.txt.REMOVED.git-id b/external/boringssl/crypto/curve25519/ed25519_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..cc7556c08b --- /dev/null +++ b/external/boringssl/crypto/curve25519/ed25519_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +4d43417d44eaceb588add4a29d87e300ec368c92 \ No newline at end of file diff --git a/external/boringssl/crypto/curve25519/internal.h b/external/boringssl/crypto/curve25519/internal.h new file mode 100644 index 0000000000..ea206a3e9b --- /dev/null +++ b/external/boringssl/crypto/curve25519/internal.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CURVE25519_INTERNAL_H +#define OPENSSL_HEADER_CURVE25519_INTERNAL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \ + !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM) +#define BORINGSSL_X25519_X86_64 + +void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]); +#endif + + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) +#define BORINGSSL_X25519_NEON + +/* x25519_NEON is defined in asm/x25519-arm.S. */ +void x25519_NEON(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]); +#endif + +/* fe means field element. Here the field is \Z/(2^255-19). An element t, + * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 + * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on + * context. */ +typedef int32_t fe[10]; + +/* ge means group element. + + * Here the group is the set of pairs (x,y) of field elements (see fe.h) + * satisfying -x^2 + y^2 = 1 + d x^2y^2 + * where d = -121665/121666. + * + * Representations: + * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z + * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T + * ge_precomp (Duif): (y+x,y-x,2dxy) */ + +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p3; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p1p1; + +typedef struct { + fe yplusx; + fe yminusx; + fe xy2d; +} ge_precomp; + +typedef struct { + fe YplusX; + fe YminusX; + fe Z; + fe T2d; +} ge_cached; + +void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h); +int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s); +void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p); +void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); +void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); +void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); +void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); +void x25519_ge_scalarmult_small_precomp( + ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]); +void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]); +void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A); +void x25519_sc_reduce(uint8_t *s); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CURVE25519_INTERNAL_H */ diff --git a/external/boringssl/crypto/curve25519/spake25519.c b/external/boringssl/crypto/curve25519/spake25519.c new file mode 100644 index 0000000000..617418cfbd --- /dev/null +++ b/external/boringssl/crypto/curve25519/spake25519.c @@ -0,0 +1,464 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include +#include + +#include "internal.h" + + +/* The following precomputation tables are for the following + * points used in the SPAKE2 protocol. + * + * N: + * x: 49918732221787544735331783592030787422991506689877079631459872391322455579424 + * y: 54629554431565467720832445949441049581317094546788069926228343916274969994000 + * encoded: 10e3df0ae37d8e7a99b5fe74b44672103dbddcbd06af680d71329a11693bc778 + * + * M: + * x: 31406539342727633121250288103050113562375374900226415211311216773867585644232 + * y: 21177308356423958466833845032658859666296341766942662650232962324899758529114 + * encoded: 5ada7e4bf6ddd9adb6626d32131c6b5c51a1e347a3478f53cfcf441b88eed12e + * + * These points and their precomputation tables are generated with the + * following Python code. For a description of the precomputation table, + * see curve25519.c in this directory. + * + * Exact copies of the source code are kept in bug 27296743. + * + * import hashlib + * import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py + * + * SEED_N = 'edwards25519 point generation seed (N)' + * SEED_M = 'edwards25519 point generation seed (M)' + * + * def genpoint(seed): + * v = hashlib.sha256(seed).digest() + * it = 1 + * while True: + * try: + * x,y = E.decodepoint(v) + * except Exception, e: + * print e + * it += 1 + * v = hashlib.sha256(v).digest() + * continue + * print "Found in %d iterations:" % it + * print " x = %d" % x + * print " y = %d" % y + * print " Encoded (hex)" + * print E.encodepoint((x,y)).encode('hex') + * return (x,y) + * + * def gentable(P): + * t = [] + * for i in range(1,16): + * k = (i >> 3 & 1) * (1 << 192) + \ + * (i >> 2 & 1) * (1 << 128) + \ + * (i >> 1 & 1) * (1 << 64) + \ + * (i & 1) + * t.append(E.scalarmult(P, k)) + * return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t) + * + * def printtable(table, name): + * print "static const uint8_t %s[15 * 2 * 32] = {" % name, + * for i in range(15 * 2 * 32): + * if i % 12 == 0: + * print "\n ", + * print " 0x%02x," % ord(table[i]), + * print "\n};" + * + * if __name__ == "__main__": + * print "Searching for N" + * N = genpoint(SEED_N) + * print "Generating precomputation table for N" + * Ntable = gentable(N) + * printtable(Ntable, "kSpakeNSmallPrecomp") + * + * print "Searching for M" + * M = genpoint(SEED_M) + * print "Generating precomputation table for M" + * Mtable = gentable(M) + * printtable(Mtable, "kSpakeMSmallPrecomp") + */ +static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = { + 0x20, 0x1b, 0xc5, 0xb3, 0x43, 0x17, 0x71, 0x10, 0x44, 0x1e, 0x73, 0xb3, + 0xae, 0x3f, 0xbf, 0x9f, 0xf5, 0x44, 0xc8, 0x13, 0x8f, 0xd1, 0x01, 0xc2, + 0x8a, 0x1a, 0x6d, 0xea, 0x4d, 0x00, 0x5d, 0x6e, 0x10, 0xe3, 0xdf, 0x0a, + 0xe3, 0x7d, 0x8e, 0x7a, 0x99, 0xb5, 0xfe, 0x74, 0xb4, 0x46, 0x72, 0x10, + 0x3d, 0xbd, 0xdc, 0xbd, 0x06, 0xaf, 0x68, 0x0d, 0x71, 0x32, 0x9a, 0x11, + 0x69, 0x3b, 0xc7, 0x78, 0x93, 0xf1, 0x57, 0x97, 0x6e, 0xf0, 0x6e, 0x45, + 0x37, 0x4a, 0xf4, 0x0b, 0x18, 0x51, 0xf5, 0x4f, 0x67, 0x3c, 0xdc, 0xec, + 0x84, 0xed, 0xd0, 0xeb, 0xca, 0xfb, 0xdb, 0xff, 0x7f, 0xeb, 0xa8, 0x23, + 0x68, 0x87, 0x13, 0x64, 0x6a, 0x10, 0xf7, 0x45, 0xe0, 0x0f, 0x32, 0x21, + 0x59, 0x7c, 0x0e, 0x50, 0xad, 0x56, 0xd7, 0x12, 0x69, 0x7b, 0x58, 0xf8, + 0xb9, 0x3b, 0xa5, 0xbb, 0x4d, 0x1b, 0x87, 0x1c, 0x46, 0xa7, 0x17, 0x9d, + 0x6d, 0x84, 0x45, 0xbe, 0x7f, 0x95, 0xd2, 0x34, 0xcd, 0x89, 0x95, 0xc0, + 0xf0, 0xd3, 0xdf, 0x6e, 0x10, 0x4a, 0xe3, 0x7b, 0xce, 0x7f, 0x40, 0x27, + 0xc7, 0x2b, 0xab, 0x66, 0x03, 0x59, 0xb4, 0x7b, 0xc7, 0xc7, 0xf0, 0x39, + 0x9a, 0x33, 0x35, 0xbf, 0xcc, 0x2f, 0xf3, 0x2e, 0x68, 0x9d, 0x53, 0x5c, + 0x88, 0x52, 0xe3, 0x77, 0x90, 0xa1, 0x27, 0x85, 0xc5, 0x74, 0x7f, 0x23, + 0x0e, 0x93, 0x01, 0x3e, 0xe7, 0x2e, 0x2e, 0x95, 0xf3, 0x0d, 0xc2, 0x25, + 0x25, 0x39, 0x39, 0x3d, 0x6e, 0x8e, 0x89, 0xbd, 0xe8, 0xbb, 0x67, 0x5e, + 0x8c, 0x66, 0x8b, 0x63, 0x28, 0x1e, 0x4e, 0x74, 0x85, 0xa8, 0xaf, 0x0f, + 0x12, 0x5d, 0xb6, 0x8a, 0x83, 0x1a, 0x77, 0x76, 0x5e, 0x62, 0x8a, 0xa7, + 0x3c, 0xb8, 0x05, 0x57, 0x2b, 0xaf, 0x36, 0x2e, 0x10, 0x90, 0xb2, 0x39, + 0xb4, 0x3e, 0x75, 0x6d, 0x3a, 0xa8, 0x31, 0x35, 0xc2, 0x1e, 0x8f, 0xc2, + 0x79, 0x89, 0x35, 0x16, 0x26, 0xd1, 0xc7, 0x0b, 0x04, 0x1f, 0x1d, 0xf9, + 0x9c, 0x05, 0xa6, 0x6b, 0xb5, 0x19, 0x5a, 0x24, 0x6d, 0x91, 0xc5, 0x31, + 0xfd, 0xc5, 0xfa, 0xe7, 0xa6, 0xcb, 0x0e, 0x4b, 0x18, 0x0d, 0x94, 0xc7, + 0xee, 0x1d, 0x46, 0x1f, 0x92, 0xb1, 0xb2, 0x4a, 0x2b, 0x43, 0x37, 0xfe, + 0xc2, 0x15, 0x11, 0x89, 0xef, 0x59, 0x73, 0x3c, 0x06, 0x76, 0x78, 0xcb, + 0xa6, 0x0d, 0x79, 0x5f, 0x28, 0x0b, 0x5b, 0x8c, 0x9e, 0xe4, 0xaa, 0x51, + 0x9a, 0x42, 0x6f, 0x11, 0x50, 0x3d, 0x01, 0xd6, 0x21, 0xc0, 0x99, 0x5e, + 0x1a, 0xe8, 0x81, 0x25, 0x80, 0xeb, 0xed, 0x5d, 0x37, 0x47, 0x30, 0x70, + 0xa0, 0x4e, 0x0b, 0x43, 0x17, 0xbe, 0xb6, 0x47, 0xe7, 0x2a, 0x62, 0x9d, + 0x5d, 0xa6, 0xc5, 0x33, 0x62, 0x9d, 0x56, 0x24, 0x9d, 0x1d, 0xb2, 0x13, + 0xbc, 0x17, 0x66, 0x43, 0xd1, 0x68, 0xd5, 0x3b, 0x17, 0x69, 0x17, 0xa6, + 0x06, 0x9e, 0x12, 0xb8, 0x7c, 0xd5, 0xaf, 0x3e, 0x21, 0x1b, 0x31, 0xeb, + 0x0b, 0xa4, 0x98, 0x1c, 0xf2, 0x6a, 0x5e, 0x7c, 0x9b, 0x45, 0x8f, 0xb2, + 0x12, 0x06, 0xd5, 0x8c, 0x1d, 0xb2, 0xa7, 0x57, 0x5f, 0x2f, 0x4f, 0xdb, + 0x52, 0x99, 0x7c, 0x58, 0x01, 0x5f, 0xf2, 0xa5, 0xf6, 0x51, 0x86, 0x21, + 0x2f, 0x5b, 0x8d, 0x6a, 0xae, 0x83, 0x34, 0x6d, 0x58, 0x4b, 0xef, 0xfe, + 0xbf, 0x73, 0x5d, 0xdb, 0xc4, 0x97, 0x2a, 0x85, 0xf3, 0x6c, 0x46, 0x42, + 0xb3, 0x90, 0xc1, 0x57, 0x97, 0x50, 0x35, 0xb1, 0x9d, 0xb7, 0xc7, 0x3c, + 0x85, 0x6d, 0x6c, 0xfd, 0xce, 0xb0, 0xc9, 0xa2, 0x77, 0xee, 0xc3, 0x6b, + 0x0c, 0x37, 0xfa, 0x30, 0x91, 0xd1, 0x2c, 0xb8, 0x5e, 0x7f, 0x81, 0x5f, + 0x87, 0xfd, 0x18, 0x02, 0x5a, 0x30, 0x4e, 0x62, 0xbc, 0x65, 0xc6, 0xce, + 0x1a, 0xcf, 0x2b, 0xaa, 0x56, 0x3e, 0x4d, 0xcf, 0xba, 0x62, 0x5f, 0x9a, + 0xd0, 0x72, 0xff, 0xef, 0x28, 0xbd, 0xbe, 0xd8, 0x57, 0x3d, 0xf5, 0x57, + 0x7d, 0xe9, 0x71, 0x31, 0xec, 0x98, 0x90, 0x94, 0xd9, 0x54, 0xbf, 0x84, + 0x0b, 0xe3, 0x06, 0x47, 0x19, 0x9a, 0x13, 0x1d, 0xef, 0x9d, 0x13, 0xf3, + 0xdb, 0xc3, 0x5c, 0x72, 0x9e, 0xed, 0x24, 0xaa, 0x64, 0xed, 0xe7, 0x0d, + 0xa0, 0x7c, 0x73, 0xba, 0x9b, 0x86, 0xa7, 0x3b, 0x55, 0xab, 0x58, 0x30, + 0xf1, 0x15, 0x81, 0x83, 0x2f, 0xf9, 0x62, 0x84, 0x98, 0x66, 0xf6, 0x55, + 0x21, 0xd8, 0xf2, 0x25, 0x64, 0x71, 0x4b, 0x12, 0x76, 0x59, 0xc5, 0xaa, + 0x93, 0x67, 0xc3, 0x86, 0x25, 0xab, 0x4e, 0x4b, 0xf6, 0xd8, 0x3f, 0x44, + 0x2e, 0x11, 0xe0, 0xbd, 0x6a, 0xf2, 0x5d, 0xf5, 0xf9, 0x53, 0xea, 0xa4, + 0xc8, 0xd9, 0x50, 0x33, 0x81, 0xd9, 0xa8, 0x2d, 0x91, 0x7d, 0x13, 0x2a, + 0x11, 0xcf, 0xde, 0x3f, 0x0a, 0xd2, 0xbc, 0x33, 0xb2, 0x62, 0x53, 0xea, + 0x77, 0x88, 0x43, 0x66, 0x27, 0x43, 0x85, 0xe9, 0x5f, 0x55, 0xf5, 0x2a, + 0x8a, 0xac, 0xdf, 0xff, 0x9b, 0x4c, 0x96, 0x9c, 0xa5, 0x7a, 0xce, 0xd5, + 0x79, 0x18, 0xf1, 0x0b, 0x58, 0x95, 0x7a, 0xe7, 0xd3, 0x74, 0x65, 0x0b, + 0xa4, 0x64, 0x30, 0xe8, 0x5c, 0xfc, 0x55, 0x56, 0xee, 0x14, 0x14, 0xd3, + 0x45, 0x3b, 0xf8, 0xde, 0x05, 0x3e, 0xb9, 0x3c, 0xd7, 0x6a, 0x52, 0x72, + 0x5b, 0x39, 0x09, 0xbe, 0x82, 0x23, 0x10, 0x4a, 0xb7, 0xc3, 0xdc, 0x4c, + 0x5d, 0xc9, 0xf1, 0x14, 0x83, 0xf9, 0x0b, 0x9b, 0xe9, 0x23, 0x84, 0x6a, + 0xc4, 0x08, 0x3d, 0xda, 0x3d, 0x12, 0x95, 0x87, 0x18, 0xa4, 0x7d, 0x3f, + 0x23, 0xde, 0xd4, 0x1e, 0xa8, 0x47, 0xc3, 0x71, 0xdb, 0xf5, 0x03, 0x6c, + 0x57, 0xe7, 0xa4, 0x43, 0x82, 0x33, 0x7b, 0x62, 0x46, 0x7d, 0xf7, 0x10, + 0x69, 0x18, 0x38, 0x27, 0x9a, 0x6f, 0x38, 0xac, 0xfa, 0x92, 0xc5, 0xae, + 0x66, 0xa6, 0x73, 0x95, 0x15, 0x0e, 0x4c, 0x04, 0xb6, 0xfc, 0xf5, 0xc7, + 0x21, 0x3a, 0x99, 0xdb, 0x0e, 0x36, 0xf0, 0x56, 0xbc, 0x75, 0xf9, 0x87, + 0x9b, 0x11, 0x18, 0x92, 0x64, 0x1a, 0xe7, 0xc7, 0xab, 0x5a, 0xc7, 0x26, + 0x7f, 0x13, 0x98, 0x42, 0x52, 0x43, 0xdb, 0xc8, 0x6d, 0x0b, 0xb7, 0x31, + 0x93, 0x24, 0xd6, 0xe8, 0x24, 0x1f, 0x6f, 0x21, 0xa7, 0x8c, 0xeb, 0xdb, + 0x83, 0xb8, 0x89, 0xe3, 0xc1, 0xd7, 0x69, 0x3b, 0x02, 0x6b, 0x54, 0x0f, + 0x84, 0x2f, 0xb5, 0x5c, 0x17, 0x77, 0xbe, 0xe5, 0x61, 0x0d, 0xc5, 0xdf, + 0x3b, 0xcf, 0x3e, 0x93, 0x4f, 0xf5, 0x89, 0xb9, 0x5a, 0xc5, 0x29, 0x31, + 0xc0, 0xc2, 0xff, 0xe5, 0x3f, 0xa6, 0xac, 0x03, 0xca, 0xf5, 0xff, 0xe0, + 0x36, 0xce, 0xf3, 0xe2, 0xb7, 0x9c, 0x02, 0xe9, 0x9e, 0xd2, 0xbc, 0x87, + 0x2f, 0x3d, 0x9a, 0x1d, 0x8f, 0xc5, 0x72, 0xb8, 0xa2, 0x01, 0xd4, 0x68, + 0xb1, 0x84, 0x16, 0x10, 0xf6, 0xf3, 0x52, 0x25, 0xd9, 0xdc, 0x4c, 0xdd, + 0x0f, 0xd6, 0x4a, 0xcf, 0x60, 0x96, 0x7e, 0xcc, 0x42, 0x0f, 0x64, 0x9d, + 0x72, 0x46, 0x04, 0x07, 0xf2, 0x5b, 0xf4, 0x07, 0xd1, 0xf4, 0x59, 0x71, +}; + +static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = { + 0xc8, 0xa6, 0x63, 0xc5, 0x97, 0xf1, 0xee, 0x40, 0xab, 0x62, 0x42, 0xee, + 0x25, 0x6f, 0x32, 0x6c, 0x75, 0x2c, 0xa7, 0xd3, 0xbd, 0x32, 0x3b, 0x1e, + 0x11, 0x9c, 0xbd, 0x04, 0xa9, 0x78, 0x6f, 0x45, 0x5a, 0xda, 0x7e, 0x4b, + 0xf6, 0xdd, 0xd9, 0xad, 0xb6, 0x62, 0x6d, 0x32, 0x13, 0x1c, 0x6b, 0x5c, + 0x51, 0xa1, 0xe3, 0x47, 0xa3, 0x47, 0x8f, 0x53, 0xcf, 0xcf, 0x44, 0x1b, + 0x88, 0xee, 0xd1, 0x2e, 0x03, 0x89, 0xaf, 0xc0, 0x61, 0x2d, 0x9e, 0x35, + 0xeb, 0x0e, 0x03, 0xe0, 0xb7, 0xfb, 0xa5, 0xbc, 0x44, 0xbe, 0x0c, 0x89, + 0x0a, 0x0f, 0xd6, 0x59, 0x47, 0x9e, 0xe6, 0x3d, 0x36, 0x9d, 0xff, 0x44, + 0x5e, 0xac, 0xab, 0xe5, 0x3a, 0xd5, 0xb0, 0x35, 0x9f, 0x6d, 0x7f, 0xba, + 0xc0, 0x85, 0x0e, 0xf4, 0x70, 0x3f, 0x13, 0x90, 0x4c, 0x50, 0x1a, 0xee, + 0xc5, 0xeb, 0x69, 0xfe, 0x98, 0x42, 0x87, 0x1d, 0xce, 0x6c, 0x29, 0xaa, + 0x2b, 0x31, 0xc2, 0x38, 0x7b, 0x6b, 0xee, 0x88, 0x0b, 0xba, 0xce, 0xa8, + 0xca, 0x19, 0x60, 0x1b, 0x16, 0xf1, 0x25, 0x1e, 0xcf, 0x63, 0x66, 0x1e, + 0xbb, 0x63, 0xeb, 0x7d, 0xca, 0xd2, 0xb4, 0x23, 0x5a, 0x01, 0x6f, 0x05, + 0xd1, 0xdc, 0x41, 0x73, 0x75, 0xc0, 0xfd, 0x30, 0x91, 0x52, 0x68, 0x96, + 0x45, 0xb3, 0x66, 0x01, 0x3b, 0x53, 0x89, 0x3c, 0x69, 0xbc, 0x6c, 0x69, + 0xe3, 0x51, 0x8f, 0xe3, 0xd2, 0x84, 0xd5, 0x28, 0x66, 0xb5, 0xe6, 0x06, + 0x09, 0xfe, 0x6d, 0xb0, 0x72, 0x16, 0xe0, 0x8a, 0xce, 0x61, 0x65, 0xa9, + 0x21, 0x32, 0x48, 0xdc, 0x7a, 0x1d, 0xe1, 0x38, 0x7f, 0x8c, 0x75, 0x88, + 0x3d, 0x08, 0xa9, 0x4a, 0x6f, 0x3d, 0x9f, 0x7f, 0x3f, 0xbd, 0x57, 0x6b, + 0x19, 0xce, 0x3f, 0x4a, 0xc9, 0xd3, 0xf9, 0x6e, 0x72, 0x7b, 0x5b, 0x74, + 0xea, 0xbe, 0x9c, 0x7a, 0x6d, 0x9c, 0x40, 0x49, 0xe6, 0xfb, 0x2a, 0x1a, + 0x75, 0x70, 0xe5, 0x4e, 0xed, 0x74, 0xe0, 0x75, 0xac, 0xc0, 0xb1, 0x11, + 0x3e, 0xf2, 0xaf, 0x88, 0x4d, 0x66, 0xb6, 0xf6, 0x15, 0x4f, 0x3c, 0x6c, + 0x77, 0xae, 0x47, 0x51, 0x63, 0x9a, 0xfe, 0xe1, 0xb4, 0x1a, 0x12, 0xdf, + 0xe9, 0x54, 0x8d, 0x3b, 0x30, 0x2a, 0x75, 0xe3, 0xe5, 0x29, 0xb1, 0x4c, + 0xb0, 0x7c, 0x6d, 0xb5, 0xae, 0x85, 0xdb, 0x1e, 0x38, 0x55, 0x96, 0xa5, + 0x5b, 0x9f, 0x15, 0x23, 0x28, 0x36, 0xb8, 0xa2, 0x41, 0xb4, 0xd7, 0x19, + 0x91, 0x8d, 0x26, 0x3e, 0xca, 0x9c, 0x05, 0x7a, 0x2b, 0x60, 0x45, 0x86, + 0x8b, 0xee, 0x64, 0x6f, 0x5c, 0x09, 0x4d, 0x4b, 0x5a, 0x7f, 0xb0, 0xc3, + 0x26, 0x9d, 0x8b, 0xb8, 0x83, 0x69, 0xcf, 0x16, 0x72, 0x62, 0x3e, 0x5e, + 0x53, 0x4f, 0x9c, 0x73, 0x76, 0xfc, 0x19, 0xef, 0xa0, 0x74, 0x3a, 0x11, + 0x1e, 0xd0, 0x4d, 0xb7, 0x87, 0xa1, 0xd6, 0x87, 0x6c, 0x0e, 0x6c, 0x8c, + 0xe9, 0xa0, 0x44, 0xc4, 0x72, 0x3e, 0x73, 0x17, 0x13, 0xd1, 0x4e, 0x3d, + 0x8e, 0x1d, 0x5a, 0x8b, 0x75, 0xcb, 0x59, 0x2c, 0x47, 0x87, 0x15, 0x41, + 0xfe, 0x08, 0xe9, 0xa6, 0x97, 0x17, 0x08, 0x26, 0x6a, 0xb5, 0xbb, 0x73, + 0xaa, 0xb8, 0x5b, 0x65, 0x65, 0x5b, 0x30, 0x9e, 0x62, 0x59, 0x02, 0xf8, + 0xb8, 0x0f, 0x32, 0x10, 0xc1, 0x36, 0x08, 0x52, 0x98, 0x4a, 0x1e, 0xf0, + 0xab, 0x21, 0x5e, 0xde, 0x16, 0x0c, 0xda, 0x09, 0x99, 0x6b, 0x9e, 0xc0, + 0x90, 0xa5, 0x5a, 0xcc, 0xb0, 0xb7, 0xbb, 0xd2, 0x8b, 0x5f, 0xd3, 0x3b, + 0x3e, 0x8c, 0xa5, 0x71, 0x66, 0x06, 0xe3, 0x28, 0xd4, 0xf8, 0x3f, 0xe5, + 0x27, 0xdf, 0xfe, 0x0f, 0x09, 0xb2, 0x8a, 0x09, 0x5a, 0x23, 0x61, 0x0d, + 0x2d, 0xf5, 0x44, 0xf1, 0x5c, 0xf8, 0x82, 0x4e, 0xdc, 0x78, 0x7a, 0xab, + 0xc3, 0x57, 0x91, 0xaf, 0x65, 0x6e, 0x71, 0xf1, 0x44, 0xbf, 0xed, 0x43, + 0x50, 0xb4, 0x67, 0x48, 0xef, 0x5a, 0x10, 0x46, 0x81, 0xb4, 0x0c, 0xc8, + 0x48, 0xed, 0x99, 0x7a, 0x45, 0xa5, 0x92, 0xc3, 0x69, 0xd6, 0xd7, 0x8a, + 0x20, 0x1b, 0xeb, 0x8f, 0xb2, 0xff, 0xec, 0x6d, 0x76, 0x04, 0xf8, 0xc2, + 0x58, 0x9b, 0xf2, 0x20, 0x53, 0xc4, 0x74, 0x91, 0x19, 0xdd, 0x2d, 0x12, + 0x53, 0xc7, 0x6e, 0xd0, 0x02, 0x51, 0x3c, 0xa6, 0x7d, 0x80, 0x75, 0x6b, + 0x1d, 0xdf, 0xf8, 0x6a, 0x52, 0xbb, 0x81, 0xf8, 0x30, 0x45, 0xef, 0x51, + 0x85, 0x36, 0xbe, 0x8e, 0xcf, 0x0b, 0x9a, 0x46, 0xe8, 0x3f, 0x99, 0xfd, + 0xf7, 0xd9, 0x3e, 0x84, 0xe5, 0xe3, 0x37, 0xcf, 0x98, 0x7f, 0xeb, 0x5e, + 0x5a, 0x53, 0x77, 0x1c, 0x20, 0xdc, 0xf1, 0x20, 0x99, 0xec, 0x60, 0x40, + 0x93, 0xef, 0x5c, 0x1c, 0x81, 0xe2, 0xa5, 0xad, 0x2a, 0xc2, 0xdb, 0x6b, + 0xc1, 0x7e, 0x8f, 0xa9, 0x23, 0x5b, 0xd9, 0x0d, 0xfe, 0xa0, 0xac, 0x11, + 0x28, 0xba, 0x8e, 0x92, 0x07, 0x2d, 0x07, 0x40, 0x83, 0x14, 0x4c, 0x35, + 0x8d, 0xd0, 0x11, 0xff, 0x98, 0xdb, 0x00, 0x30, 0x6f, 0x65, 0xb6, 0xa0, + 0x7f, 0x9c, 0x08, 0xb8, 0xce, 0xb3, 0xa8, 0x42, 0xd3, 0x84, 0x45, 0xe1, + 0xe3, 0x8f, 0xa6, 0x89, 0x21, 0xd7, 0x74, 0x02, 0x4d, 0x64, 0xdf, 0x54, + 0x15, 0x9e, 0xba, 0x12, 0x49, 0x09, 0x41, 0xf6, 0x10, 0x24, 0xa1, 0x84, + 0x15, 0xfd, 0x68, 0x6a, 0x57, 0x66, 0xb3, 0x6d, 0x4c, 0xea, 0xbf, 0xbc, + 0x60, 0x3f, 0x52, 0x1c, 0x44, 0x1b, 0xc0, 0x4a, 0x25, 0xe3, 0xd9, 0x4c, + 0x9a, 0x74, 0xad, 0xfc, 0x9e, 0x8d, 0x0b, 0x18, 0x66, 0x24, 0xd1, 0x06, + 0xac, 0x68, 0xc1, 0xae, 0x14, 0xce, 0xb1, 0xf3, 0x86, 0x9f, 0x87, 0x11, + 0xd7, 0x9f, 0x30, 0x92, 0xdb, 0xec, 0x0b, 0x4a, 0xe8, 0xf6, 0x53, 0x36, + 0x68, 0x12, 0x11, 0x5e, 0xe0, 0x34, 0xa4, 0xff, 0x00, 0x0a, 0x26, 0xb8, + 0x62, 0x79, 0x9c, 0x0c, 0xd5, 0xe5, 0xf5, 0x1c, 0x1a, 0x16, 0x84, 0x4d, + 0x8e, 0x5d, 0x31, 0x7e, 0xf7, 0xe2, 0xd3, 0xa1, 0x41, 0x90, 0x61, 0x5d, + 0x04, 0xb2, 0x9a, 0x18, 0x9e, 0x54, 0xfb, 0xd1, 0x61, 0x95, 0x1b, 0x08, + 0xca, 0x7c, 0x49, 0x44, 0x74, 0x1d, 0x2f, 0xca, 0xc4, 0x7a, 0xe1, 0x8b, + 0x2f, 0xbb, 0x96, 0xee, 0x19, 0x8a, 0x5d, 0xfb, 0x3e, 0x82, 0xe7, 0x15, + 0xdb, 0x29, 0x14, 0xee, 0xc9, 0x4d, 0x9a, 0xfb, 0x9f, 0x8a, 0xbb, 0x17, + 0x37, 0x1b, 0x6e, 0x28, 0x6c, 0xf9, 0xff, 0xb5, 0xb5, 0x8b, 0x9d, 0x88, + 0x20, 0x08, 0x10, 0xd7, 0xca, 0x58, 0xf6, 0xe1, 0x32, 0x91, 0x6f, 0x36, + 0xc0, 0xad, 0xc1, 0x57, 0x5d, 0x76, 0x31, 0x43, 0xf3, 0xdd, 0xec, 0xf1, + 0xa9, 0x79, 0xe9, 0xe9, 0x85, 0xd7, 0x91, 0xc7, 0x31, 0x62, 0x3c, 0xd2, + 0x90, 0x2c, 0x9c, 0xa4, 0x56, 0x37, 0x7b, 0xbe, 0x40, 0x58, 0xc0, 0x81, + 0x83, 0x22, 0xe8, 0x13, 0x79, 0x18, 0xdb, 0x3a, 0x1b, 0x31, 0x0d, 0x00, + 0x6c, 0x22, 0x62, 0x75, 0x70, 0xd8, 0x96, 0x59, 0x99, 0x44, 0x79, 0x71, + 0xa6, 0x76, 0x81, 0x28, 0xb2, 0x65, 0xe8, 0x47, 0x14, 0xc6, 0x39, 0x06, +}; + +enum spake2_state_t { + spake2_state_init = 0, + spake2_state_msg_generated, + spake2_state_key_generated, +}; + +struct spake2_ctx_st { + uint8_t private_key[32]; + uint8_t my_msg[32]; + uint8_t password_scalar[32]; + uint8_t password_hash[SHA512_DIGEST_LENGTH]; + uint8_t *my_name; + size_t my_name_len; + uint8_t *their_name; + size_t their_name_len; + enum spake2_role_t my_role; + enum spake2_state_t state; +}; + +SPAKE2_CTX *SPAKE2_CTX_new(enum spake2_role_t my_role, + const uint8_t *my_name, size_t my_name_len, + const uint8_t *their_name, size_t their_name_len) { + SPAKE2_CTX *ctx = OPENSSL_malloc(sizeof(SPAKE2_CTX)); + if (ctx == NULL) { + return NULL; + } + + memset(ctx, 0, sizeof(SPAKE2_CTX)); + ctx->my_role = my_role; + + CBS my_name_cbs, their_name_cbs; + CBS_init(&my_name_cbs, my_name, my_name_len); + CBS_init(&their_name_cbs, their_name, their_name_len); + if (!CBS_stow(&my_name_cbs, &ctx->my_name, &ctx->my_name_len) || + !CBS_stow(&their_name_cbs, &ctx->their_name, &ctx->their_name_len)) { + SPAKE2_CTX_free(ctx); + return NULL; + } + + return ctx; +} + +void SPAKE2_CTX_free(SPAKE2_CTX *ctx) { + if (ctx == NULL) { + return; + } + + OPENSSL_free(ctx->my_name); + OPENSSL_free(ctx->their_name); + OPENSSL_free(ctx); +} + +/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian + * order. */ +static void left_shift_3(uint8_t n[32]) { + uint8_t carry = 0; + unsigned i; + + for (i = 0; i < 32; i++) { + const uint8_t next_carry = n[i] >> 5; + n[i] = (n[i] << 3) | carry; + carry = next_carry; + } +} + +int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t *password, + size_t password_len) { + if (ctx->state != spake2_state_init) { + return 0; + } + + if (max_out_len < sizeof(ctx->my_msg)) { + return 0; + } + + uint8_t private_tmp[64]; + RAND_bytes(private_tmp, sizeof(private_tmp)); + x25519_sc_reduce(private_tmp); + /* Multiply by the cofactor (eight) so that we'll clear it when operating on + * the peer's point later in the protocol. */ + left_shift_3(private_tmp); + memcpy(ctx->private_key, private_tmp, sizeof(ctx->private_key)); + + ge_p3 P; + x25519_ge_scalarmult_base(&P, ctx->private_key); + + /* mask = h(password) * . */ + uint8_t password_tmp[SHA512_DIGEST_LENGTH]; + SHA512(password, password_len, password_tmp); + memcpy(ctx->password_hash, password_tmp, sizeof(ctx->password_hash)); + x25519_sc_reduce(password_tmp); + memcpy(ctx->password_scalar, password_tmp, sizeof(ctx->password_scalar)); + + ge_p3 mask; + x25519_ge_scalarmult_small_precomp(&mask, ctx->password_scalar, + ctx->my_role == spake2_role_alice + ? kSpakeMSmallPrecomp + : kSpakeNSmallPrecomp); + + /* P* = P + mask. */ + ge_cached mask_cached; + x25519_ge_p3_to_cached(&mask_cached, &mask); + ge_p1p1 Pstar; + x25519_ge_add(&Pstar, &P, &mask_cached); + + /* Encode P* */ + ge_p2 Pstar_proj; + x25519_ge_p1p1_to_p2(&Pstar_proj, &Pstar); + x25519_ge_tobytes(ctx->my_msg, &Pstar_proj); + + memcpy(out, ctx->my_msg, sizeof(ctx->my_msg)); + *out_len = sizeof(ctx->my_msg); + ctx->state = spake2_state_msg_generated; + + return 1; +} + +static void update_with_length_prefix(SHA512_CTX *sha, const uint8_t *data, + const size_t len) { + uint8_t len_le[8]; + size_t l = len; + unsigned i; + + for (i = 0; i < 8; i++) { + len_le[i] = l & 0xff; + l >>= 8; + } + + SHA512_Update(sha, len_le, sizeof(len_le)); + SHA512_Update(sha, data, len); +} + +int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, size_t *out_key_len, + size_t max_out_key_len, const uint8_t *their_msg, + size_t their_msg_len) { + if (ctx->state != spake2_state_msg_generated || + their_msg_len != 32) { + return 0; + } + + ge_p3 Qstar; + if (0 != x25519_ge_frombytes_vartime(&Qstar, their_msg)) { + /* Point received from peer was not on the curve. */ + return 0; + } + + /* Unmask peer's value. */ + ge_p3 peers_mask; + x25519_ge_scalarmult_small_precomp(&peers_mask, ctx->password_scalar, + ctx->my_role == spake2_role_alice + ? kSpakeNSmallPrecomp + : kSpakeMSmallPrecomp); + + ge_cached peers_mask_cached; + x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask); + + ge_p1p1 Q_compl; + ge_p3 Q_ext; + x25519_ge_sub(&Q_compl, &Qstar, &peers_mask_cached); + x25519_ge_p1p1_to_p3(&Q_ext, &Q_compl); + + ge_p2 dh_shared; + x25519_ge_scalarmult(&dh_shared, ctx->private_key, &Q_ext); + + uint8_t dh_shared_encoded[32]; + x25519_ge_tobytes(dh_shared_encoded, &dh_shared); + + SHA512_CTX sha; + SHA512_Init(&sha); + if (ctx->my_role == spake2_role_alice) { + update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len); + update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len); + update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg)); + update_with_length_prefix(&sha, their_msg, 32); + } else { + update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len); + update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len); + update_with_length_prefix(&sha, their_msg, 32); + update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg)); + } + update_with_length_prefix(&sha, dh_shared_encoded, sizeof(dh_shared_encoded)); + update_with_length_prefix(&sha, ctx->password_hash, + sizeof(ctx->password_hash)); + + uint8_t key[SHA512_DIGEST_LENGTH]; + SHA512_Final(key, &sha); + + size_t to_copy = max_out_key_len; + if (to_copy > sizeof(key)) { + to_copy = sizeof(key); + } + memcpy(out_key, key, to_copy); + *out_key_len = to_copy; + ctx->state = spake2_state_key_generated; + + return 1; +} diff --git a/external/boringssl/crypto/curve25519/spake25519_test.cc b/external/boringssl/crypto/curve25519/spake25519_test.cc new file mode 100644 index 0000000000..d97a8602af --- /dev/null +++ b/external/boringssl/crypto/curve25519/spake25519_test.cc @@ -0,0 +1,169 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include "../test/scoped_types.h" + + +struct SPAKE2Run { + bool Run() { + ScopedSPAKE2_CTX alice(SPAKE2_CTX_new( + spake2_role_alice, + reinterpret_cast(alice_names.first.data()), + alice_names.first.size(), + reinterpret_cast(alice_names.second.data()), + alice_names.second.size())); + ScopedSPAKE2_CTX bob(SPAKE2_CTX_new( + spake2_role_bob, + reinterpret_cast(bob_names.first.data()), + bob_names.first.size(), + reinterpret_cast(bob_names.second.data()), + bob_names.second.size())); + + if (!alice || !bob) { + return false; + } + + uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE]; + uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE]; + size_t alice_msg_len, bob_msg_len; + + if (!SPAKE2_generate_msg( + alice.get(), alice_msg, &alice_msg_len, sizeof(alice_msg), + reinterpret_cast(alice_password.data()), + alice_password.size()) || + !SPAKE2_generate_msg( + bob.get(), bob_msg, &bob_msg_len, sizeof(bob_msg), + reinterpret_cast(bob_password.data()), + bob_password.size())) { + return false; + } + + if (alice_corrupt_msg_bit >= 0 && + static_cast(alice_corrupt_msg_bit) < 8 * alice_msg_len) { + alice_msg[alice_corrupt_msg_bit/8] ^= 1 << (alice_corrupt_msg_bit & 7); + } + + uint8_t alice_key[64], bob_key[64]; + size_t alice_key_len, bob_key_len; + + if (!SPAKE2_process_msg(alice.get(), alice_key, &alice_key_len, + sizeof(alice_key), bob_msg, bob_msg_len) || + !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len, sizeof(bob_key), + alice_msg, alice_msg_len)) { + return false; + } + + key_matches_ = (alice_key_len == bob_key_len && + memcmp(alice_key, bob_key, alice_key_len) == 0); + + return true; + } + + bool key_matches() const { + return key_matches_; + } + + std::string alice_password = "password"; + std::string bob_password = "password"; + std::pair alice_names = {"alice", "bob"}; + std::pair bob_names = {"bob", "alice"}; + int alice_corrupt_msg_bit = -1; + + private: + bool key_matches_ = false; +}; + +static bool TestSPAKE2() { + for (unsigned i = 0; i < 20; i++) { + SPAKE2Run spake2; + if (!spake2.Run()) { + fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n"); + return false; + } + + if (!spake2.key_matches()) { + fprintf(stderr, "Key didn't match for equal passwords.\n"); + return false; + } + } + + return true; +} + +static bool TestWrongPassword() { + SPAKE2Run spake2; + spake2.bob_password = "wrong password"; + if (!spake2.Run()) { + fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n"); + return false; + } + + if (spake2.key_matches()) { + fprintf(stderr, "Key matched for unequal passwords.\n"); + return false; + } + + return true; +} + +static bool TestWrongNames() { + SPAKE2Run spake2; + spake2.alice_names.second = "charlie"; + spake2.bob_names.second = "charlie"; + if (!spake2.Run()) { + fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n"); + return false; + } + + if (spake2.key_matches()) { + fprintf(stderr, "Key matched for unequal names.\n"); + return false; + } + + return true; +} + +static bool TestCorruptMessages() { + for (int i = 0; i < 8 * SPAKE2_MAX_MSG_SIZE; i++) { + SPAKE2Run spake2; + spake2.alice_corrupt_msg_bit = i; + if (spake2.Run() && spake2.key_matches()) { + fprintf(stderr, "Passed after corrupting Alice's message, bit %d\n", i); + return false; + } + } + + return true; +} + +/* TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down. */ + +int main(int argc, char **argv) { + if (!TestSPAKE2() || + !TestWrongPassword() || + !TestWrongNames() || + !TestCorruptMessages()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/curve25519/x25519-x86_64.c b/external/boringssl/crypto/curve25519/x25519-x86_64.c new file mode 100644 index 0000000000..1bd86a09f3 --- /dev/null +++ b/external/boringssl/crypto/curve25519/x25519-x86_64.c @@ -0,0 +1,246 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP + * 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as + * public domain but this file has the ISC license just to keep licencing + * simple. + * + * The field functions are shared by Ed25519 and X25519 where possible. */ + +#include + +#include + +#include "internal.h" + + +#if defined(BORINGSSL_X25519_X86_64) + +typedef struct { uint64_t v[5]; } fe25519; + +/* These functions are defined in asm/x25519-x86_64.S */ +void x25519_x86_64_work_cswap(fe25519 *, uint64_t); +void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b); +void x25519_x86_64_square(fe25519 *out, const fe25519 *a); +void x25519_x86_64_freeze(fe25519 *); +void x25519_x86_64_ladderstep(fe25519 *work); + +static void fe25519_setint(fe25519 *r, unsigned v) { + r->v[0] = v; + r->v[1] = 0; + r->v[2] = 0; + r->v[3] = 0; + r->v[4] = 0; +} + +/* Assumes input x being reduced below 2^255 */ +static void fe25519_pack(unsigned char r[32], const fe25519 *x) { + fe25519 t; + t = *x; + x25519_x86_64_freeze(&t); + + r[0] = (uint8_t)(t.v[0] & 0xff); + r[1] = (uint8_t)((t.v[0] >> 8) & 0xff); + r[2] = (uint8_t)((t.v[0] >> 16) & 0xff); + r[3] = (uint8_t)((t.v[0] >> 24) & 0xff); + r[4] = (uint8_t)((t.v[0] >> 32) & 0xff); + r[5] = (uint8_t)((t.v[0] >> 40) & 0xff); + r[6] = (uint8_t)((t.v[0] >> 48)); + + r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8); + r[7] = (uint8_t)((t.v[1] >> 5) & 0xff); + r[8] = (uint8_t)((t.v[1] >> 13) & 0xff); + r[9] = (uint8_t)((t.v[1] >> 21) & 0xff); + r[10] = (uint8_t)((t.v[1] >> 29) & 0xff); + r[11] = (uint8_t)((t.v[1] >> 37) & 0xff); + r[12] = (uint8_t)((t.v[1] >> 45)); + + r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0); + r[13] = (uint8_t)((t.v[2] >> 2) & 0xff); + r[14] = (uint8_t)((t.v[2] >> 10) & 0xff); + r[15] = (uint8_t)((t.v[2] >> 18) & 0xff); + r[16] = (uint8_t)((t.v[2] >> 26) & 0xff); + r[17] = (uint8_t)((t.v[2] >> 34) & 0xff); + r[18] = (uint8_t)((t.v[2] >> 42) & 0xff); + r[19] = (uint8_t)((t.v[2] >> 50)); + + r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe); + r[20] = (uint8_t)((t.v[3] >> 7) & 0xff); + r[21] = (uint8_t)((t.v[3] >> 15) & 0xff); + r[22] = (uint8_t)((t.v[3] >> 23) & 0xff); + r[23] = (uint8_t)((t.v[3] >> 31) & 0xff); + r[24] = (uint8_t)((t.v[3] >> 39) & 0xff); + r[25] = (uint8_t)((t.v[3] >> 47)); + + r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0); + r[26] = (uint8_t)((t.v[4] >> 4) & 0xff); + r[27] = (uint8_t)((t.v[4] >> 12) & 0xff); + r[28] = (uint8_t)((t.v[4] >> 20) & 0xff); + r[29] = (uint8_t)((t.v[4] >> 28) & 0xff); + r[30] = (uint8_t)((t.v[4] >> 36) & 0xff); + r[31] = (uint8_t)((t.v[4] >> 44)); +} + +static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) { + r->v[0] = x[0]; + r->v[0] += (uint64_t)x[1] << 8; + r->v[0] += (uint64_t)x[2] << 16; + r->v[0] += (uint64_t)x[3] << 24; + r->v[0] += (uint64_t)x[4] << 32; + r->v[0] += (uint64_t)x[5] << 40; + r->v[0] += ((uint64_t)x[6] & 7) << 48; + + r->v[1] = x[6] >> 3; + r->v[1] += (uint64_t)x[7] << 5; + r->v[1] += (uint64_t)x[8] << 13; + r->v[1] += (uint64_t)x[9] << 21; + r->v[1] += (uint64_t)x[10] << 29; + r->v[1] += (uint64_t)x[11] << 37; + r->v[1] += ((uint64_t)x[12] & 63) << 45; + + r->v[2] = x[12] >> 6; + r->v[2] += (uint64_t)x[13] << 2; + r->v[2] += (uint64_t)x[14] << 10; + r->v[2] += (uint64_t)x[15] << 18; + r->v[2] += (uint64_t)x[16] << 26; + r->v[2] += (uint64_t)x[17] << 34; + r->v[2] += (uint64_t)x[18] << 42; + r->v[2] += ((uint64_t)x[19] & 1) << 50; + + r->v[3] = x[19] >> 1; + r->v[3] += (uint64_t)x[20] << 7; + r->v[3] += (uint64_t)x[21] << 15; + r->v[3] += (uint64_t)x[22] << 23; + r->v[3] += (uint64_t)x[23] << 31; + r->v[3] += (uint64_t)x[24] << 39; + r->v[3] += ((uint64_t)x[25] & 15) << 47; + + r->v[4] = x[25] >> 4; + r->v[4] += (uint64_t)x[26] << 4; + r->v[4] += (uint64_t)x[27] << 12; + r->v[4] += (uint64_t)x[28] << 20; + r->v[4] += (uint64_t)x[29] << 28; + r->v[4] += (uint64_t)x[30] << 36; + r->v[4] += ((uint64_t)x[31] & 127) << 44; +} + +static void fe25519_invert(fe25519 *r, const fe25519 *x) { + fe25519 z2; + fe25519 z9; + fe25519 z11; + fe25519 z2_5_0; + fe25519 z2_10_0; + fe25519 z2_20_0; + fe25519 z2_50_0; + fe25519 z2_100_0; + fe25519 t; + int i; + + /* 2 */ x25519_x86_64_square(&z2, x); + /* 4 */ x25519_x86_64_square(&t, &z2); + /* 8 */ x25519_x86_64_square(&t, &t); + /* 9 */ x25519_x86_64_mul(&z9, &t, x); + /* 11 */ x25519_x86_64_mul(&z11, &z9, &z2); + /* 22 */ x25519_x86_64_square(&t, &z11); + /* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9); + + /* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0); + /* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); } + /* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0); + + /* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0); + /* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); } + /* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0); + + /* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0); + /* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); } + /* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0); + + /* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t); + /* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); } + /* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0); + + /* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0); + /* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); } + /* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0); + + /* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0); + /* 2^200 - 2^100 */ for (i = 1; i < 100; i++) { + x25519_x86_64_square(&t, &t); + } + /* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0); + + /* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t); + /* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); } + /* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0); + + /* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t); + /* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t); + /* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t); + + /* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t); + + /* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t); + /* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11); +} + +static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) { + fe25519 work[5]; + + work[0] = *xr; + fe25519_setint(work + 1, 1); + fe25519_setint(work + 2, 0); + work[3] = *xr; + fe25519_setint(work + 4, 1); + + int i, j; + uint8_t prevbit = 0; + + j = 6; + for (i = 31; i >= 0; i--) { + while (j >= 0) { + const uint8_t bit = 1 & (s[i] >> j); + const uint64_t swap = bit ^ prevbit; + prevbit = bit; + x25519_x86_64_work_cswap(work + 1, swap); + x25519_x86_64_ladderstep(work); + j -= 1; + } + j = 7; + } + + *xr = work[1]; + *zr = work[2]; +} + +void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]) { + uint8_t e[32]; + memcpy(e, scalar, sizeof(e)); + + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fe25519 t; + fe25519 z; + fe25519_unpack(&t, point); + mladder(&t, &z, e); + fe25519_invert(&z, &z); + x25519_x86_64_mul(&t, &t, &z); + fe25519_pack(out, &t); +} + +#endif /* BORINGSSL_X25519_X86_64 */ diff --git a/external/boringssl/crypto/curve25519/x25519_test.cc b/external/boringssl/crypto/curve25519/x25519_test.cc new file mode 100644 index 0000000000..24dfa650c9 --- /dev/null +++ b/external/boringssl/crypto/curve25519/x25519_test.cc @@ -0,0 +1,126 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include + + +static bool TestX25519() { + /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */ + static const uint8_t kScalar1[32] = { + 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, + 0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, + 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4, + }; + static const uint8_t kPoint1[32] = { + 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, + 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, + 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c, + }; + + uint8_t out[32]; + X25519(out, kScalar1, kPoint1); + + static const uint8_t kExpected1[32] = { + 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, + 0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, + 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52, + }; + if (memcmp(kExpected1, out, sizeof(out)) != 0) { + fprintf(stderr, "X25519 test one failed.\n"); + return false; + } + + static const uint8_t kScalar2[32] = { + 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, + 0x91, 0x95, 0x7d, 0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, + 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d, + }; + static const uint8_t kPoint2[32] = { + 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, + 0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, + 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93, + }; + + X25519(out, kScalar2, kPoint2); + + static const uint8_t kExpected2[32] = { + 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, + 0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, + 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57, + }; + if (memcmp(kExpected2, out, sizeof(out)) != 0) { + fprintf(stderr, "X25519 test two failed.\n"); + return false; + } + + return true; +} + +static bool TestX25519SmallOrder() { + static const uint8_t kSmallOrderPoint[32] = { + 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, + 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, + 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, + }; + + uint8_t out[32], private_key[32]; + memset(private_key, 0x11, sizeof(private_key)); + + if (X25519(out, private_key, kSmallOrderPoint)) { + fprintf(stderr, "X25519 returned success with a small-order input.\n"); + return false; + } + + return true; +} + +static bool TestX25519Iterated() { + /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */ + uint8_t scalar[32] = {9}, point[32] = {9}, out[32]; + + unsigned i; + for (i = 0; i < 1000; i++) { + X25519(out, scalar, point); + memcpy(point, scalar, sizeof(point)); + memcpy(scalar, out, sizeof(scalar)); + } + + static const uint8_t kExpected[32] = { + 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef, + 0x56, 0x6f, 0x2f, 0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, + 0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51, + }; + + if (memcmp(kExpected, scalar, sizeof(kExpected)) != 0) { + fprintf(stderr, "Iterated X25519 test failed\n"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + if (!TestX25519() || + !TestX25519Iterated() || + !TestX25519SmallOrder()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/des/CMakeLists.txt b/external/boringssl/crypto/des/CMakeLists.txt new file mode 100644 index 0000000000..f61fa14a66 --- /dev/null +++ b/external/boringssl/crypto/des/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + des + + OBJECT + + des.c +) diff --git a/external/boringssl/crypto/des/des.c b/external/boringssl/crypto/des/des.c new file mode 100644 index 0000000000..1d27ebe4b2 --- /dev/null +++ b/external/boringssl/crypto/des/des.c @@ -0,0 +1,771 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "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; + int i; + + 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; + schedule->subkeys[i][0] = ROTATE(t2, 30) & 0xffffffffL; + + t2 = ((s >> 16L) | (t & 0xffff0000L)); + schedule->subkeys[i][1] = ROTATE(t2, 26) & 0xffffffffL; + } +} + +static const uint8_t kOddParity[256] = { + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, + 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, + 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, + 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, + 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, + 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, + 91, 91, 93, 93, 94, 94, 97, 97, 98, 98, 100, 100, 103, 103, 104, + 104, 107, 107, 109, 109, 110, 110, 112, 112, 115, 115, 117, 117, 118, 118, + 121, 121, 122, 122, 124, 124, 127, 127, 128, 128, 131, 131, 133, 133, 134, + 134, 137, 137, 138, 138, 140, 140, 143, 143, 145, 145, 146, 146, 148, 148, + 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 161, 161, 162, 162, 164, + 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174, 176, 176, 179, 179, + 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191, 193, 193, 194, + 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206, 208, 208, + 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223, 224, + 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239, + 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, + 254 +}; + +void DES_set_odd_parity(DES_cblock *key) { + unsigned i; + + for (i = 0; i < DES_KEY_SZ; i++) { + key->bytes[i] = kOddParity[key->bytes[i]]; + } +} + +static void DES_encrypt1(uint32_t *data, const DES_key_schedule *ks, int enc) { + uint32_t l, r, t, u; + + 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; + + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (enc) { + D_ENCRYPT(ks, l, r, 0); + D_ENCRYPT(ks, r, l, 1); + D_ENCRYPT(ks, l, r, 2); + D_ENCRYPT(ks, r, l, 3); + D_ENCRYPT(ks, l, r, 4); + D_ENCRYPT(ks, r, l, 5); + D_ENCRYPT(ks, l, r, 6); + D_ENCRYPT(ks, r, l, 7); + D_ENCRYPT(ks, l, r, 8); + D_ENCRYPT(ks, r, l, 9); + D_ENCRYPT(ks, l, r, 10); + D_ENCRYPT(ks, r, l, 11); + D_ENCRYPT(ks, l, r, 12); + D_ENCRYPT(ks, r, l, 13); + D_ENCRYPT(ks, l, r, 14); + D_ENCRYPT(ks, r, l, 15); + } else { + D_ENCRYPT(ks, l, r, 15); + D_ENCRYPT(ks, r, l, 14); + D_ENCRYPT(ks, l, r, 13); + D_ENCRYPT(ks, r, l, 12); + D_ENCRYPT(ks, l, r, 11); + D_ENCRYPT(ks, r, l, 10); + D_ENCRYPT(ks, l, r, 9); + D_ENCRYPT(ks, r, l, 8); + D_ENCRYPT(ks, l, r, 7); + D_ENCRYPT(ks, r, l, 6); + D_ENCRYPT(ks, l, r, 5); + D_ENCRYPT(ks, r, l, 4); + D_ENCRYPT(ks, l, r, 3); + D_ENCRYPT(ks, r, l, 2); + D_ENCRYPT(ks, l, r, 1); + D_ENCRYPT(ks, r, l, 0); + } + + /* 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; + + 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; + + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (enc) { + D_ENCRYPT(ks, l, r, 0); + D_ENCRYPT(ks, r, l, 1); + D_ENCRYPT(ks, l, r, 2); + D_ENCRYPT(ks, r, l, 3); + D_ENCRYPT(ks, l, r, 4); + D_ENCRYPT(ks, r, l, 5); + D_ENCRYPT(ks, l, r, 6); + D_ENCRYPT(ks, r, l, 7); + D_ENCRYPT(ks, l, r, 8); + D_ENCRYPT(ks, r, l, 9); + D_ENCRYPT(ks, l, r, 10); + D_ENCRYPT(ks, r, l, 11); + D_ENCRYPT(ks, l, r, 12); + D_ENCRYPT(ks, r, l, 13); + D_ENCRYPT(ks, l, r, 14); + D_ENCRYPT(ks, r, l, 15); + } else { + D_ENCRYPT(ks, l, r, 15); + D_ENCRYPT(ks, r, l, 14); + D_ENCRYPT(ks, l, r, 13); + D_ENCRYPT(ks, r, l, 12); + D_ENCRYPT(ks, l, r, 11); + D_ENCRYPT(ks, r, l, 10); + D_ENCRYPT(ks, l, r, 9); + D_ENCRYPT(ks, r, l, 8); + D_ENCRYPT(ks, l, r, 7); + D_ENCRYPT(ks, r, l, 6); + D_ENCRYPT(ks, l, r, 5); + D_ENCRYPT(ks, r, l, 4); + D_ENCRYPT(ks, l, r, 3); + D_ENCRYPT(ks, r, l, 2); + D_ENCRYPT(ks, l, r, 1); + D_ENCRYPT(ks, r, l, 0); + } + /* rotate and clear the top bits on machines with 8byte longs */ + data[0] = ROTATE(l, 3) & 0xffffffffL; + data[1] = ROTATE(r, 3) & 0xffffffffL; +} + +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; +} + +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_ecb3_encrypt(const DES_cblock *input, DES_cblock *output, + const DES_key_schedule *ks1, const DES_key_schedule *ks2, + const DES_key_schedule *ks3, int enc) { + uint32_t l0, l1; + uint32_t ll[2]; + const uint8_t *in = input->bytes; + uint8_t *out = output->bytes; + + c2l(in, l0); + c2l(in, l1); + ll[0] = l0; + ll[1] = l1; + if (enc) { + DES_encrypt3(ll, ks1, ks2, ks3); + } else { + DES_decrypt3(ll, ks1, ks2, ks3); + } + l0 = ll[0]; + l1 = ll[1]; + l2c(l0, out); + l2c(l1, out); +} + +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; +} + +void DES_ede2_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + DES_cblock *ivec, + int enc) { + DES_ede3_cbc_encrypt(in, out, len, ks1, ks2, ks1, ivec, enc); +} + + +/* Deprecated functions. */ + +void DES_set_key_unchecked(const DES_cblock *key, DES_key_schedule *schedule) { + DES_set_key(key, schedule); +} diff --git a/external/boringssl/crypto/des/internal.h b/external/boringssl/crypto/des/internal.h new file mode 100644 index 0000000000..00b45586ff --- /dev/null +++ b/external/boringssl/crypto/des/internal.h @@ -0,0 +1,212 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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 + +#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<> (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(ks, R, S, u, t, E0, E1) \ + u = R ^ ks->subkeys[S][0]; \ + t = R ^ ks->subkeys[S][1] + +#define D_ENCRYPT(ks, LL, R, S) \ + { \ + LOAD_DATA(ks, 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 + +#define ROTATE(a, n) (((a) >> (n)) + ((a) << (32 - (n)))) + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_DES_INTERNAL_H */ diff --git a/external/boringssl/crypto/dh/CMakeLists.txt b/external/boringssl/crypto/dh/CMakeLists.txt new file mode 100644 index 0000000000..2f3a6deddc --- /dev/null +++ b/external/boringssl/crypto/dh/CMakeLists.txt @@ -0,0 +1,25 @@ +include_directories(../../include) + +add_library( + dh + + OBJECT + + dh.c + params.c + check.c + dh_asn1.c +) + +if(ENABLE_TESTS) +add_executable( + dh_test + + dh_test.cc + + $ +) + +target_link_libraries(dh_test crypto) +add_dependencies(all_tests dh_test) +endif() diff --git a/external/boringssl/crypto/dh/check.c b/external/boringssl/crypto/dh/check.c new file mode 100644 index 0000000000..d27fdf1540 --- /dev/null +++ b/external/boringssl/crypto/dh/check.c @@ -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.] */ + +#include + +#include + +#include "internal.h" + + +int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { + *ret = 0; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + + int ok = 0; + + /* Check |pub_key| is greater than 1. */ + BIGNUM *tmp = BN_CTX_get(ctx); + if (tmp == NULL || + !BN_set_word(tmp, 1)) { + goto err; + } + if (BN_cmp(pub_key, tmp) <= 0) { + *ret |= DH_CHECK_PUBKEY_TOO_SMALL; + } + + /* Check |pub_key| is less than |dh->p| - 1. */ + if (!BN_copy(tmp, dh->p) || + !BN_sub_word(tmp, 1)) { + goto err; + } + if (BN_cmp(pub_key, tmp) >= 0) { + *ret |= DH_CHECK_PUBKEY_TOO_LARGE; + } + + if (dh->q != NULL) { + /* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114 + * groups which are not safe primes but pick a generator on a prime-order + * subgroup of size |dh->q|. */ + if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) { + goto err; + } + if (!BN_is_one(tmp)) { + *ret |= DH_CHECK_PUBKEY_INVALID; + } + } + + ok = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + 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/external/boringssl/crypto/dh/dh.c b/external/boringssl/crypto/dh/dh.c new file mode 100644 index 0000000000..94eb3643c6 --- /dev/null +++ b/external/boringssl/crypto/dh/dh.c @@ -0,0 +1,460 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +#define OPENSSL_DH_MAX_MODULUS_BITS 10000 + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +DH *DH_new(void) { + DH *dh = OPENSSL_malloc(sizeof(DH)); + if (dh == NULL) { + OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(dh, 0, sizeof(DH)); + + CRYPTO_MUTEX_init(&dh->method_mont_p_lock); + + dh->references = 1; + CRYPTO_new_ex_data(&dh->ex_data); + + return dh; +} + +void DH_free(DH *dh) { + if (dh == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) { + return; + } + + CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data); + + BN_MONT_CTX_free(dh->method_mont_p); + BN_clear_free(dh->p); + BN_clear_free(dh->g); + BN_clear_free(dh->q); + BN_clear_free(dh->j); + OPENSSL_free(dh->seed); + BN_clear_free(dh->counter); + BN_clear_free(dh->pub_key); + BN_clear_free(dh->priv_key); + CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock); + + OPENSSL_free(dh); +} + +int DH_generate_parameters_ex(DH *dh, 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 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 |dh| has the necessary elements */ + if (dh->p == NULL) { + dh->p = BN_new(); + if (dh->p == NULL) { + goto err; + } + } + if (dh->g == NULL) { + dh->g = BN_new(); + if (dh->g == NULL) { + goto err; + } + } + + if (generator <= 1) { + OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR); + goto err; + } + if (generator == DH_GENERATOR_2) { + if (!BN_set_word(t1, 24)) { + goto err; + } + if (!BN_set_word(t2, 11)) { + 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(dh->p, prime_bits, 1, t1, t2, cb)) { + goto err; + } + if (!BN_GENCB_call(cb, 3, 0)) { + goto err; + } + if (!BN_set_word(dh->g, g)) { + goto err; + } + ok = 1; + +err: + if (!ok) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + } + + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} + +int DH_generate_key(DH *dh) { + int ok = 0; + int generate_new_key = 0; + unsigned l; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + BIGNUM local_priv; + + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); + goto err; + } + + 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; + } + + if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, + dh->p, ctx)) { + 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_consttime(pub_key, dh->g, &local_priv, dh->p, ctx, + dh->method_mont_p)) { + goto err; + } + + dh->pub_key = pub_key; + dh->priv_key = priv_key; + ok = 1; + +err: + if (ok != 1) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + } + + if (dh->pub_key == NULL) { + BN_free(pub_key); + } + if (dh->priv_key == NULL) { + BN_free(priv_key); + } + BN_CTX_free(ctx); + return ok; +} + +int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) { + BN_CTX *ctx = 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, 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, DH_R_NO_PRIVATE_VALUE); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, + dh->p, ctx)) { + goto err; + } + + if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) { + OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY); + goto err; + } + + BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(shared_key, peers_key, &local_priv, dh->p, ctx, + dh->method_mont_p)) { + OPENSSL_PUT_ERROR(DH, 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; +} + +int DH_size(const DH *dh) { return BN_num_bytes(dh->p); } + +unsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); } + +int DH_up_ref(DH *dh) { + CRYPTO_refcount_inc(&dh->references); + 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; + } + } + + 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; + } + + 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_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +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/external/boringssl/crypto/dh/dh_asn1.c b/external/boringssl/crypto/dh/dh_asn1.c new file mode 100644 index 0000000000..1a147eea91 --- /dev/null +++ b/external/boringssl/crypto/dh/dh_asn1.c @@ -0,0 +1,160 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + +#include "../bytestring/internal.h" + + +static int parse_integer(CBS *cbs, BIGNUM **out) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + return BN_parse_asn1_unsigned(cbs, *out); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* A DH object may be missing some components. */ + OPENSSL_PUT_ERROR(DH, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return BN_marshal_asn1(cbb, bn); +} + +DH *DH_parse_parameters(CBS *cbs) { + DH *ret = DH_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->g)) { + goto err; + } + + uint64_t priv_length; + if (CBS_len(&child) != 0) { + if (!CBS_get_asn1_uint64(&child, &priv_length) || + priv_length > UINT_MAX) { + goto err; + } + ret->priv_length = (unsigned)priv_length; + } + + if (CBS_len(&child) != 0) { + goto err; + } + + return ret; + +err: + OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR); + DH_free(ret); + return NULL; +} + +int DH_marshal_parameters(CBB *cbb, const DH *dh) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dh->p) || + !marshal_integer(&child, dh->g) || + (dh->priv_length != 0 && + !CBB_add_asn1_uint64(&child, dh->priv_length)) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DH, DH_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DH *d2i_DHparams(DH **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DH *ret = DH_parse_parameters(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DH_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DHparams(const DH *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DH_marshal_parameters(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} diff --git a/external/boringssl/crypto/dh/dh_test.cc b/external/boringssl/crypto/dh/dh_test.cc new file mode 100644 index 0000000000..1c2442833b --- /dev/null +++ b/external/boringssl/crypto/dh/dh_test.cc @@ -0,0 +1,626 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../test/scoped_types.h" + + +static bool RunBasicTests(); +static bool RunRFC5114Tests(); +static bool TestBadY(); +static bool TestASN1(); + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + if (!RunBasicTests() || + !RunRFC5114Tests() || + !TestBadY() || + !TestASN1()) { + ERR_print_errors_fp(stderr); + return 1; + } + + printf("PASS\n"); + return 0; +} + +static int GenerateCallback(int p, int n, BN_GENCB *arg) { + char c = '*'; + + if (p == 0) { + c = '.'; + } else if (p == 1) { + c = '+'; + } else if (p == 2) { + c = '*'; + } else if (p == 3) { + c = '\n'; + } + FILE *out = reinterpret_cast(arg->arg); + fputc(c, out); + fflush(out); + + return 1; +} + +static bool RunBasicTests() { + BN_GENCB cb; + BN_GENCB_set(&cb, &GenerateCallback, stdout); + ScopedDH a(DH_new()); + if (!a || !DH_generate_parameters_ex(a.get(), 64, DH_GENERATOR_5, &cb)) { + return false; + } + + int check_result; + if (!DH_check(a.get(), &check_result)) { + return false; + } + if (check_result & DH_CHECK_P_NOT_PRIME) { + printf("p value is not prime\n"); + } + if (check_result & DH_CHECK_P_NOT_SAFE_PRIME) { + printf("p value is not a safe prime\n"); + } + if (check_result & DH_CHECK_UNABLE_TO_CHECK_GENERATOR) { + printf("unable to check the generator value\n"); + } + if (check_result & DH_CHECK_NOT_SUITABLE_GENERATOR) { + printf("the g value is not a generator\n"); + } + + printf("\np = "); + BN_print_fp(stdout, a->p); + printf("\ng = "); + BN_print_fp(stdout, a->g); + printf("\n"); + + ScopedDH b(DH_new()); + if (!b) { + return false; + } + + b->p = BN_dup(a->p); + b->g = BN_dup(a->g); + if (b->p == nullptr || b->g == nullptr) { + return false; + } + + if (!DH_generate_key(a.get())) { + return false; + } + printf("pri1 = "); + BN_print_fp(stdout, a->priv_key); + printf("\npub1 = "); + BN_print_fp(stdout, a->pub_key); + printf("\n"); + + if (!DH_generate_key(b.get())) { + return false; + } + printf("pri2 = "); + BN_print_fp(stdout, b->priv_key); + printf("\npub2 = "); + BN_print_fp(stdout, b->pub_key); + printf("\n"); + + std::vector key1(DH_size(a.get())); + int ret = DH_compute_key(key1.data(), b->pub_key, a.get()); + if (ret < 0) { + return false; + } + key1.resize(ret); + + printf("key1 = "); + for (size_t i = 0; i < key1.size(); i++) { + printf("%02x", key1[i]); + } + printf("\n"); + + std::vector key2(DH_size(b.get())); + ret = DH_compute_key(key2.data(), a->pub_key, b.get()); + if (ret < 0) { + return false; + } + key2.resize(ret); + + printf("key2 = "); + for (size_t i = 0; i < key2.size(); i++) { + printf("%02x", key2[i]); + } + printf("\n"); + + if (key1.size() < 4 || key1 != key2) { + fprintf(stderr, "Error in DH routines\n"); + return false; + } + + return true; +} + +/* Test data from RFC 5114 */ + +static const uint8_t kDHTest1024_160_xA[] = { + 0xB9, 0xA3, 0xB3, 0xAE, 0x8F, 0xEF, 0xC1, 0xA2, 0x93, 0x04, + 0x96, 0x50, 0x70, 0x86, 0xF8, 0x45, 0x5D, 0x48, 0x94, 0x3E}; +static const uint8_t kDHTest1024_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 uint8_t kDHTest1024_160_xB[] = { + 0x93, 0x92, 0xC9, 0xF9, 0xEB, 0x6A, 0x7A, 0x6A, 0x90, 0x22, + 0xF7, 0xD8, 0x3E, 0x72, 0x23, 0xC6, 0x83, 0x5B, 0xBD, 0xDA}; +static const uint8_t kDHTest1024_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 uint8_t kDHTest1024_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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 uint8_t kDHTest2048_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}; + +struct RFC5114TestData { + DH *(*get_param)(const ENGINE *engine); + const uint8_t *xA; + size_t xA_len; + const uint8_t *yA; + size_t yA_len; + const uint8_t *xB; + size_t xB_len; + const uint8_t *yB; + size_t yB_len; + const uint8_t *Z; + size_t Z_len; +}; + +#define MAKE_RFC5114_TEST_DATA(pre) \ + { \ + DH_get_##pre, kDHTest##pre##_xA, sizeof(kDHTest##pre##_xA), \ + kDHTest##pre##_yA, sizeof(kDHTest##pre##_yA), kDHTest##pre##_xB, \ + sizeof(kDHTest##pre##_xB), kDHTest##pre##_yB, \ + sizeof(kDHTest##pre##_yB), kDHTest##pre##_Z, sizeof(kDHTest##pre##_Z) \ + } + +static const RFC5114TestData kRFCTestData[] = { + MAKE_RFC5114_TEST_DATA(1024_160), + MAKE_RFC5114_TEST_DATA(2048_224), + MAKE_RFC5114_TEST_DATA(2048_256), + }; + +static bool RunRFC5114Tests() { + for (unsigned i = 0; i < sizeof(kRFCTestData) / sizeof(RFC5114TestData); i++) { + const RFC5114TestData *td = kRFCTestData + i; + /* Set up DH structures setting key components */ + ScopedDH dhA(td->get_param(nullptr)); + ScopedDH dhB(td->get_param(nullptr)); + if (!dhA || !dhB) { + fprintf(stderr, "Initialisation error RFC5114 set %u\n", i + 1); + return false; + } + + dhA->priv_key = BN_bin2bn(td->xA, td->xA_len, nullptr); + dhA->pub_key = BN_bin2bn(td->yA, td->yA_len, nullptr); + + dhB->priv_key = BN_bin2bn(td->xB, td->xB_len, nullptr); + dhB->pub_key = BN_bin2bn(td->yB, td->yB_len, nullptr); + + if (!dhA->priv_key || !dhA->pub_key || !dhB->priv_key || !dhB->pub_key) { + fprintf(stderr, "BN_bin2bn error RFC5114 set %u\n", i + 1); + return false; + } + + if ((td->Z_len != (size_t)DH_size(dhA.get())) || + (td->Z_len != (size_t)DH_size(dhB.get()))) { + return false; + } + + std::vector Z1(DH_size(dhA.get())); + std::vector Z2(DH_size(dhB.get())); + /* Work out shared secrets using both sides and compare + * with expected values. */ + int ret1 = DH_compute_key(Z1.data(), dhB->pub_key, dhA.get()); + int ret2 = DH_compute_key(Z2.data(), dhA->pub_key, dhB.get()); + if (ret1 < 0 || ret2 < 0) { + fprintf(stderr, "DH_compute_key error RFC5114 set %u\n", i + 1); + return false; + } + + if (static_cast(ret1) != td->Z_len || + memcmp(Z1.data(), td->Z, td->Z_len) != 0 || + static_cast(ret2) != td->Z_len || + memcmp(Z2.data(), td->Z, td->Z_len) != 0) { + fprintf(stderr, "Test failed RFC5114 set %u\n", i + 1); + return false; + } + + printf("RFC5114 parameter test %u OK\n", i + 1); + } + + return 1; +} + +// kRFC5114_2048_224BadY is a bad y-coordinate for RFC 5114's 2048-bit MODP +// Group with 224-bit Prime Order Subgroup (section 2.2). +static const uint8_t kRFC5114_2048_224BadY[] = { + 0x45, 0x32, 0x5f, 0x51, 0x07, 0xe5, 0xdf, 0x1c, 0xd6, 0x02, 0x82, 0xb3, + 0x32, 0x8f, 0xa4, 0x0f, 0x87, 0xb8, 0x41, 0xfe, 0xb9, 0x35, 0xde, 0xad, + 0xc6, 0x26, 0x85, 0xb4, 0xff, 0x94, 0x8c, 0x12, 0x4c, 0xbf, 0x5b, 0x20, + 0xc4, 0x46, 0xa3, 0x26, 0xeb, 0xa4, 0x25, 0xb7, 0x68, 0x8e, 0xcc, 0x67, + 0xba, 0xea, 0x58, 0xd0, 0xf2, 0xe9, 0xd2, 0x24, 0x72, 0x60, 0xda, 0x88, + 0x18, 0x9c, 0xe0, 0x31, 0x6a, 0xad, 0x50, 0x6d, 0x94, 0x35, 0x8b, 0x83, + 0x4a, 0x6e, 0xfa, 0x48, 0x73, 0x0f, 0x83, 0x87, 0xff, 0x6b, 0x66, 0x1f, + 0xa8, 0x82, 0xc6, 0x01, 0xe5, 0x80, 0xb5, 0xb0, 0x52, 0xd0, 0xe9, 0xd8, + 0x72, 0xf9, 0x7d, 0x5b, 0x8b, 0xa5, 0x4c, 0xa5, 0x25, 0x95, 0x74, 0xe2, + 0x7a, 0x61, 0x4e, 0xa7, 0x8f, 0x12, 0xe2, 0xd2, 0x9d, 0x8c, 0x02, 0x70, + 0x34, 0x44, 0x32, 0xc7, 0xb2, 0xf3, 0xb9, 0xfe, 0x17, 0x2b, 0xd6, 0x1f, + 0x8b, 0x7e, 0x4a, 0xfa, 0xa3, 0xb5, 0x3e, 0x7a, 0x81, 0x9a, 0x33, 0x66, + 0x62, 0xa4, 0x50, 0x18, 0x3e, 0xa2, 0x5f, 0x00, 0x07, 0xd8, 0x9b, 0x22, + 0xe4, 0xec, 0x84, 0xd5, 0xeb, 0x5a, 0xf3, 0x2a, 0x31, 0x23, 0xd8, 0x44, + 0x22, 0x2a, 0x8b, 0x37, 0x44, 0xcc, 0xc6, 0x87, 0x4b, 0xbe, 0x50, 0x9d, + 0x4a, 0xc4, 0x8e, 0x45, 0xcf, 0x72, 0x4d, 0xc0, 0x89, 0xb3, 0x72, 0xed, + 0x33, 0x2c, 0xbc, 0x7f, 0x16, 0x39, 0x3b, 0xeb, 0xd2, 0xdd, 0xa8, 0x01, + 0x73, 0x84, 0x62, 0xb9, 0x29, 0xd2, 0xc9, 0x51, 0x32, 0x9e, 0x7a, 0x6a, + 0xcf, 0xc1, 0x0a, 0xdb, 0x0e, 0xe0, 0x62, 0x77, 0x6f, 0x59, 0x62, 0x72, + 0x5a, 0x69, 0xa6, 0x5b, 0x70, 0xca, 0x65, 0xc4, 0x95, 0x6f, 0x9a, 0xc2, + 0xdf, 0x72, 0x6d, 0xb1, 0x1e, 0x54, 0x7b, 0x51, 0xb4, 0xef, 0x7f, 0x89, + 0x93, 0x74, 0x89, 0x59, +}; + +static bool TestBadY() { + ScopedDH dh(DH_get_2048_224(nullptr)); + ScopedBIGNUM pub_key( + BN_bin2bn(kRFC5114_2048_224BadY, sizeof(kRFC5114_2048_224BadY), nullptr)); + if (!dh || !pub_key || !DH_generate_key(dh.get())) { + return false; + } + + int flags; + if (!DH_check_pub_key(dh.get(), pub_key.get(), &flags)) { + return false; + } + if (!(flags & DH_CHECK_PUBKEY_INVALID)) { + fprintf(stderr, "DH_check_pub_key did not reject the key.\n"); + return false; + } + + std::vector result(DH_size(dh.get())); + if (DH_compute_key(result.data(), pub_key.get(), dh.get()) >= 0) { + fprintf(stderr, "DH_compute_key unexpectedly succeeded.\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +static bool BIGNUMEqualsHex(const BIGNUM *bn, const char *hex) { + BIGNUM *hex_bn = NULL; + if (!BN_hex2bn(&hex_bn, hex)) { + return false; + } + ScopedBIGNUM free_hex_bn(hex_bn); + return BN_cmp(bn, hex_bn) == 0; +} + +static bool TestASN1() { + // kParams are a set of Diffie-Hellman parameters generated with + // openssl dhparam 256 + static const uint8_t kParams[] = { + 0x30, 0x26, 0x02, 0x21, 0x00, 0xd7, 0x20, 0x34, 0xa3, 0x27, + 0x4f, 0xdf, 0xbf, 0x04, 0xfd, 0x24, 0x68, 0x25, 0xb6, 0x56, + 0xd8, 0xab, 0x2a, 0x41, 0x2d, 0x74, 0x0a, 0x52, 0x08, 0x7c, + 0x40, 0x71, 0x4e, 0xd2, 0x57, 0x93, 0x13, 0x02, 0x01, 0x02, + }; + + CBS cbs; + CBS_init(&cbs, kParams, sizeof(kParams)); + ScopedDH dh(DH_parse_parameters(&cbs)); + if (!dh || CBS_len(&cbs) != 0 || + !BIGNUMEqualsHex( + dh->p, + "d72034a3274fdfbf04fd246825b656d8ab2a412d740a52087c40714ed2579313") || + !BIGNUMEqualsHex(dh->g, "2") || dh->priv_length != 0) { + return false; + } + + ScopedCBB cbb; + uint8_t *der; + size_t der_len; + if (!CBB_init(cbb.get(), 0) || + !DH_marshal_parameters(cbb.get(), dh.get()) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + ScopedOpenSSLBytes free_der(der); + if (der_len != sizeof(kParams) || memcmp(der, kParams, der_len) != 0) { + return false; + } + + // kParamsDSA are a set of Diffie-Hellman parameters generated with + // openssl dhparam 256 -dsaparam + static const uint8_t kParamsDSA[] = { + 0x30, 0x81, 0x89, 0x02, 0x41, 0x00, 0x93, 0xf3, 0xc1, 0x18, 0x01, 0xe6, + 0x62, 0xb6, 0xd1, 0x46, 0x9a, 0x2c, 0x72, 0xea, 0x31, 0xd9, 0x18, 0x10, + 0x30, 0x28, 0x63, 0xe2, 0x34, 0x7d, 0x80, 0xca, 0xee, 0x82, 0x2b, 0x19, + 0x3c, 0x19, 0xbb, 0x42, 0x83, 0x02, 0x70, 0xdd, 0xdb, 0x8c, 0x03, 0xab, + 0xe9, 0x9c, 0xc4, 0x00, 0x4d, 0x70, 0x5f, 0x52, 0x03, 0x31, 0x2c, 0xa4, + 0x67, 0x34, 0x51, 0x95, 0x2a, 0xac, 0x11, 0xe2, 0x6a, 0x55, 0x02, 0x40, + 0x44, 0xc8, 0x10, 0x53, 0x44, 0x32, 0x31, 0x63, 0xd8, 0xd1, 0x8c, 0x75, + 0xc8, 0x98, 0x53, 0x3b, 0x5b, 0x4a, 0x2a, 0x0a, 0x09, 0xe7, 0xd0, 0x3c, + 0x53, 0x72, 0xa8, 0x6b, 0x70, 0x41, 0x9c, 0x26, 0x71, 0x44, 0xfc, 0x7f, + 0x08, 0x75, 0xe1, 0x02, 0xab, 0x74, 0x41, 0xe8, 0x2a, 0x3d, 0x3c, 0x26, + 0x33, 0x09, 0xe4, 0x8b, 0xb4, 0x41, 0xec, 0xa6, 0xa8, 0xba, 0x1a, 0x07, + 0x8a, 0x77, 0xf5, 0x5f, 0x02, 0x02, 0x00, 0xa0, + }; + + CBS_init(&cbs, kParamsDSA, sizeof(kParamsDSA)); + dh.reset(DH_parse_parameters(&cbs)); + if (!dh || CBS_len(&cbs) != 0 || + !BIGNUMEqualsHex(dh->p, + "93f3c11801e662b6d1469a2c72ea31d91810302863e2347d80caee8" + "22b193c19bb42830270dddb8c03abe99cc4004d705f5203312ca467" + "3451952aac11e26a55") || + !BIGNUMEqualsHex(dh->g, + "44c8105344323163d8d18c75c898533b5b4a2a0a09e7d03c5372a86" + "b70419c267144fc7f0875e102ab7441e82a3d3c263309e48bb441ec" + "a6a8ba1a078a77f55f") || + dh->priv_length != 160) { + return false; + } + + if (!CBB_init(cbb.get(), 0) || + !DH_marshal_parameters(cbb.get(), dh.get()) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + ScopedOpenSSLBytes free_der2(der); + if (der_len != sizeof(kParamsDSA) || memcmp(der, kParamsDSA, der_len) != 0) { + return false; + } + + return true; +} diff --git a/external/boringssl/crypto/dh/internal.h b/external/boringssl/crypto/dh/internal.h new file mode 100644 index 0000000000..81b9c90290 --- /dev/null +++ b/external/boringssl/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 + +#include +#include + +#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/external/boringssl/crypto/dh/params.c b/external/boringssl/crypto/dh/params.c new file mode 100644 index 0000000000..7e8102a014 --- /dev/null +++ b/external/boringssl/crypto/dh/params.c @@ -0,0 +1,301 @@ +/* ==================================================================== + * 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 + +#include + +#include "internal.h" +#include "../bn/internal.h" + + +static const BN_ULONG dh1024_160_p[] = { + TOBN(0xDF1FB2BC, 0x2E4A4371), TOBN(0xE68CFDA7, 0x6D4DA708), + TOBN(0x45BF37DF, 0x365C1A65), TOBN(0xA151AF5F, 0x0DC8B4BD), + TOBN(0xFAA31A4F, 0xF55BCCC0), TOBN(0x4EFFD6FA, 0xE5644738), + TOBN(0x98488E9C, 0x219A7372), TOBN(0xACCBDD7D, 0x90C4BD70), + TOBN(0x24975C3C, 0xD49B83BF), TOBN(0x13ECB4AE, 0xA9061123), + TOBN(0x9838EF1E, 0x2EE652C0), TOBN(0x6073E286, 0x75A23D18), + TOBN(0x9A6A9DCA, 0x52D23B61), TOBN(0x52C99FBC, 0xFB06A3C6), + TOBN(0xDE92DE5E, 0xAE5D54EC), TOBN(0xB10B8F96, 0xA080E01D), +}; +static const BN_ULONG dh1024_160_g[] = { + TOBN(0x855E6EEB, 0x22B3B2E5), TOBN(0x858F4DCE, 0xF97C2A24), + TOBN(0x2D779D59, 0x18D08BC8), TOBN(0xD662A4D1, 0x8E73AFA3), + TOBN(0x1DBF0A01, 0x69B6A28A), TOBN(0xA6A24C08, 0x7A091F53), + TOBN(0x909D0D22, 0x63F80A76), TOBN(0xD7FBD7D3, 0xB9A92EE1), + TOBN(0x5E91547F, 0x9E2749F4), TOBN(0x160217B4, 0xB01B886A), + TOBN(0x777E690F, 0x5504F213), TOBN(0x266FEA1E, 0x5C41564B), + TOBN(0xD6406CFF, 0x14266D31), TOBN(0xF8104DD2, 0x58AC507F), + TOBN(0x6765A442, 0xEFB99905), TOBN(0xA4D1CBD5, 0xC3FD3412), +}; +static const BN_ULONG dh1024_160_q[] = { + TOBN(0x64B7CB9D, 0x49462353), TOBN(0x81A8DF27, 0x8ABA4E7D), 0xF518AA87, +}; + +static const BN_ULONG dh2048_224_p[] = { + TOBN(0x0AC4DFFE, 0x0C10E64F), TOBN(0xCF9DE538, 0x4E71B81C), + TOBN(0x7EF363E2, 0xFFA31F71), TOBN(0xE3FB73C1, 0x6B8E75B9), + TOBN(0xC9B53DCF, 0x4BA80A29), TOBN(0x23F10B0E, 0x16E79763), + TOBN(0xC52172E4, 0x13042E9B), TOBN(0xBE60E69C, 0xC928B2B9), + TOBN(0x80CD86A1, 0xB9E587E8), TOBN(0x315D75E1, 0x98C641A4), + TOBN(0xCDF93ACC, 0x44328387), TOBN(0x15987D9A, 0xDC0A486D), + TOBN(0x7310F712, 0x1FD5A074), TOBN(0x278273C7, 0xDE31EFDC), + TOBN(0x1602E714, 0x415D9330), TOBN(0x81286130, 0xBC8985DB), + TOBN(0xB3BF8A31, 0x70918836), TOBN(0x6A00E0A0, 0xB9C49708), + TOBN(0xC6BA0B2C, 0x8BBC27BE), TOBN(0xC9F98D11, 0xED34DBF6), + TOBN(0x7AD5B7D0, 0xB6C12207), TOBN(0xD91E8FEF, 0x55B7394B), + TOBN(0x9037C9ED, 0xEFDA4DF8), TOBN(0x6D3F8152, 0xAD6AC212), + TOBN(0x1DE6B85A, 0x1274A0A6), TOBN(0xEB3D688A, 0x309C180E), + TOBN(0xAF9A3C40, 0x7BA1DF15), TOBN(0xE6FA141D, 0xF95A56DB), + TOBN(0xB54B1597, 0xB61D0A75), TOBN(0xA20D64E5, 0x683B9FD1), + TOBN(0xD660FAA7, 0x9559C51F), TOBN(0xAD107E1E, 0x9123A9D0), +}; + +static const BN_ULONG dh2048_224_g[] = { + TOBN(0x84B890D3, 0x191F2BFA), TOBN(0x81BC087F, 0x2A7065B3), + TOBN(0x19C418E1, 0xF6EC0179), TOBN(0x7B5A0F1C, 0x71CFFF4C), + TOBN(0xEDFE72FE, 0x9B6AA4BD), TOBN(0x81E1BCFE, 0x94B30269), + TOBN(0x566AFBB4, 0x8D6C0191), TOBN(0xB539CCE3, 0x409D13CD), + TOBN(0x6AA21E7F, 0x5F2FF381), TOBN(0xD9E263E4, 0x770589EF), + TOBN(0x10E183ED, 0xD19963DD), TOBN(0xB70A8137, 0x150B8EEB), + TOBN(0x051AE3D4, 0x28C8F8AC), TOBN(0xBB77A86F, 0x0C1AB15B), + TOBN(0x6E3025E3, 0x16A330EF), TOBN(0x19529A45, 0xD6F83456), + TOBN(0xF180EB34, 0x118E98D1), TOBN(0xB5F6C6B2, 0x50717CBE), + TOBN(0x09939D54, 0xDA7460CD), TOBN(0xE2471504, 0x22EA1ED4), + TOBN(0xB8A762D0, 0x521BC98A), TOBN(0xF4D02727, 0x5AC1348B), + TOBN(0xC1766910, 0x1999024A), TOBN(0xBE5E9001, 0xA8D66AD7), + TOBN(0xC57DB17C, 0x620A8652), TOBN(0xAB739D77, 0x00C29F52), + TOBN(0xDD921F01, 0xA70C4AFA), TOBN(0xA6824A4E, 0x10B9A6F0), + TOBN(0x74866A08, 0xCFE4FFE3), TOBN(0x6CDEBE7B, 0x89998CAF), + TOBN(0x9DF30B5C, 0x8FFDAC50), TOBN(0xAC4032EF, 0x4F2D9AE3), +}; + +static const BN_ULONG dh2048_224_q[] = { + TOBN(0xBF389A99, 0xB36371EB), TOBN(0x1F80535A, 0x4738CEBC), + TOBN(0xC58D93FE, 0x99717710), 0x801C0D34, +}; + +static const BN_ULONG dh2048_256_p[] = { + TOBN(0xDB094AE9, 0x1E1A1597), TOBN(0x693877FA, 0xD7EF09CA), + TOBN(0x6116D227, 0x6E11715F), TOBN(0xA4B54330, 0xC198AF12), + TOBN(0x75F26375, 0xD7014103), TOBN(0xC3A3960A, 0x54E710C3), + TOBN(0xDED4010A, 0xBD0BE621), TOBN(0xC0B857F6, 0x89962856), + TOBN(0xB3CA3F79, 0x71506026), TOBN(0x1CCACB83, 0xE6B486F6), + TOBN(0x67E144E5, 0x14056425), TOBN(0xF6A167B5, 0xA41825D9), + TOBN(0x3AD83477, 0x96524D8E), TOBN(0xF13C6D9A, 0x51BFA4AB), + TOBN(0x2D525267, 0x35488A0E), TOBN(0xB63ACAE1, 0xCAA6B790), + TOBN(0x4FDB70C5, 0x81B23F76), TOBN(0xBC39A0BF, 0x12307F5C), + TOBN(0xB941F54E, 0xB1E59BB8), TOBN(0x6C5BFC11, 0xD45F9088), + TOBN(0x22E0B1EF, 0x4275BF7B), TOBN(0x91F9E672, 0x5B4758C0), + TOBN(0x5A8A9D30, 0x6BCF67ED), TOBN(0x209E0C64, 0x97517ABD), + TOBN(0x3BF4296D, 0x830E9A7C), TOBN(0x16C3D911, 0x34096FAA), + TOBN(0xFAF7DF45, 0x61B2AA30), TOBN(0xE00DF8F1, 0xD61957D4), + TOBN(0x5D2CEED4, 0x435E3B00), TOBN(0x8CEEF608, 0x660DD0F2), + TOBN(0xFFBBD19C, 0x65195999), TOBN(0x87A8E61D, 0xB4B6663C), +}; +static const BN_ULONG dh2048_256_g[] = { + TOBN(0x664B4C0F, 0x6CC41659), TOBN(0x5E2327CF, 0xEF98C582), + TOBN(0xD647D148, 0xD4795451), TOBN(0x2F630784, 0x90F00EF8), + TOBN(0x184B523D, 0x1DB246C3), TOBN(0xC7891428, 0xCDC67EB6), + TOBN(0x7FD02837, 0x0DF92B52), TOBN(0xB3353BBB, 0x64E0EC37), + TOBN(0xECD06E15, 0x57CD0915), TOBN(0xB7D2BBD2, 0xDF016199), + TOBN(0xC8484B1E, 0x052588B9), TOBN(0xDB2A3B73, 0x13D3FE14), + TOBN(0xD052B985, 0xD182EA0A), TOBN(0xA4BD1BFF, 0xE83B9C80), + TOBN(0xDFC967C1, 0xFB3F2E55), TOBN(0xB5045AF2, 0x767164E1), + TOBN(0x1D14348F, 0x6F2F9193), TOBN(0x64E67982, 0x428EBC83), + TOBN(0x8AC376D2, 0x82D6ED38), TOBN(0x777DE62A, 0xAAB8A862), + TOBN(0xDDF463E5, 0xE9EC144B), TOBN(0x0196F931, 0xC77A57F2), + TOBN(0xA55AE313, 0x41000A65), TOBN(0x901228F8, 0xC28CBB18), + TOBN(0xBC3773BF, 0x7E8C6F62), TOBN(0xBE3A6C1B, 0x0C6B47B1), + TOBN(0xFF4FED4A, 0xAC0BB555), TOBN(0x10DBC150, 0x77BE463F), + TOBN(0x07F4793A, 0x1A0BA125), TOBN(0x4CA7B18F, 0x21EF2054), + TOBN(0x2E775066, 0x60EDBD48), TOBN(0x3FB32C9B, 0x73134D0B), +}; +static const BN_ULONG dh2048_256_q[] = { + TOBN(0xA308B0FE, 0x64F5FBD3), TOBN(0x99B1A47D, 0x1EB3750B), + TOBN(0xB4479976, 0x40129DA2), TOBN(0x8CF83642, 0xA709A097), +}; + +/* 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(0xE7393E0F, 0x24218EB3), TOBN(0x7DE0F4D6, 0xE2BD68B0), + TOBN(0x07DD62DB, 0x88AEAA74), TOBN(0x10EA9FCC, 0x9DDD3305), + TOBN(0xA7DBCA78, 0x74087D15), TOBN(0xDAE88600, 0x78045B07), + TOBN(0x33168A46, 0x1AAD3B72), TOBN(0xFF590137, 0x7BEDDCFD), + TOBN(0xFE324A46, 0x7A635E81), TOBN(0x5AC179BA, 0x420B2A29), + TOBN(0x13B4B4D7, 0x177E16D5), TOBN(0x849F912E, 0x639C72FB), + TOBN(0xB88174CB, 0x98BCE951), TOBN(0x0C84D239, 0xA45F520B), + TOBN(0x36D693D3, 0x4AFD0AD5), TOBN(0xD67DE440, 0xCBBBDC19), +}; + +/* dh1024_safe_prime_2 is hard-coded in nginx, + * src/event/ngx_event_openssl.c. */ +static const BN_ULONG dh1024_safe_prime_2[] = { + TOBN(0x071DF045, 0xCFE16B9B), TOBN(0x88D0F65D, 0x146757DA), + TOBN(0x4A63AB1E, 0x58FAFD49), TOBN(0x35D8CECE, 0xEF9EA027), + TOBN(0x25ECE662, 0x70CC9A50), TOBN(0xF29BA5DF, 0x81DC2CA7), + TOBN(0x8F68B076, 0xF7D36CC8), TOBN(0x60E91A92, 0xA757E304), + TOBN(0x87A2BC04, 0x9BE67780), TOBN(0xBEECA565, 0xA5FDF1D2), + TOBN(0x5CCBBAA8, 0x922614C5), TOBN(0x6C030276, 0xE710800C), + TOBN(0x08EED4EB, 0x0FB3504C), TOBN(0xD958A3F5, 0x68B42D4B), + TOBN(0x7C43FCF5, 0x80E9CFDB), TOBN(0xBBBC2DCA, 0xD8467490), +}; + +/* 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(0x671746AE, 0x349E721B), TOBN(0x258A0655, 0xD75E93B2), + TOBN(0xD425E6FB, 0x25592EB6), TOBN(0x0C46AB04, 0xBF7CDD9A), + TOBN(0x0AD0BC99, 0x28968680), TOBN(0xF53907FB, 0xD0B7EB49), + TOBN(0x202EABB3, 0xEBC85C1D), TOBN(0x3129C693, 0x364D8C71), + TOBN(0x53728351, 0x2D46F195), TOBN(0xDF326DD6, 0x8C76CC85), + TOBN(0xF898B3F9, 0x9188E24E), TOBN(0x95EFB13C, 0x2855DFD2), + TOBN(0x1F5DAC48, 0x7B2241FE), TOBN(0x117B6BF7, 0x99A13D9F), + TOBN(0x0F97CDDA, 0x3A3468C7), TOBN(0xC9BBF5F7, 0x74A8297B)}; + +/* 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(0x5085E21F, 0x0DD5C86B), TOBN(0x871538DF, 0xD823C650), + TOBN(0x125136F7, 0x262E56A8), TOBN(0x974E9EF1, 0x839EB5DB), + TOBN(0xEA9BAD99, 0x1B13A63C), TOBN(0x6044CF02, 0x3D76E05E), + TOBN(0x611EBBBE, 0x1BAC9B5C), TOBN(0x3E371D79, 0x4E5327DF), + TOBN(0x000E6EDD, 0x061CBC05), TOBN(0x2F971F3C, 0x20129B48), + TOBN(0xA6EF09C4, 0x3048D5A2), TOBN(0xFA15A259, 0xCBD523A6), + TOBN(0x2A206490, 0x4A79A770), TOBN(0x91B78182, 0x51BB055E), + TOBN(0x7CF180C3, 0xBDD4798E), TOBN(0xE6969D3D, 0x495BE32C)}; + +static const BN_ULONG bn_two_data[] = {2}; + +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) +}; + +static BIGNUM bn_two = STATIC_BIGNUM(bn_two_data); + +static DH *get_standard_parameters(const struct standard_parameters *params, + const ENGINE *engine) { + DH *dh = DH_new(); + if (!dh) { + return NULL; + } + + dh->p = BN_dup(¶ms->p); + dh->q = BN_dup(¶ms->q); + dh->g = BN_dup(¶ms->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) { + unsigned 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/external/boringssl/crypto/digest/CMakeLists.txt b/external/boringssl/crypto/digest/CMakeLists.txt new file mode 100644 index 0000000000..f0a0b23fd4 --- /dev/null +++ b/external/boringssl/crypto/digest/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + digest + + OBJECT + + digest.c + digests.c +) + +if(ENABLE_TESTS) +add_executable( + digest_test + + digest_test.cc + + $ +) + +target_link_libraries(digest_test crypto) +add_dependencies(all_tests digest_test) +endif() diff --git a/external/boringssl/crypto/digest/digest.c b/external/boringssl/crypto/digest/digest.c new file mode 100644 index 0000000000..fdd9fe551a --- /dev/null +++ b/external/boringssl/crypto/digest/digest.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 + +#include +#include + +#include +#include + +#include "internal.h" + + +int EVP_MD_type(const EVP_MD *md) { return 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, 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); + + out->digest = in->digest; + 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, 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); + out->pctx_ops = in->pctx_ops; + 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 > 0) { + OPENSSL_free(ctx->md_data); + ctx->md_data = NULL; + } + ctx->digest = type; + if (type->ctx_size > 0) { + ctx->md_data = OPENSSL_malloc(type->ctx_size); + if (ctx->md_data == NULL) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + } + } + + assert(ctx->pctx == NULL || ctx->pctx_ops != NULL); + + ctx->digest->init(ctx); + return 1; +} + +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) { + ctx->digest->update(ctx, data, len); + return 1; +} + +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, unsigned int *size) { + assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE); + ctx->digest->final(ctx, md_out); + if (size != NULL) { + *size = ctx->digest->md_size; + } + OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); + return 1; +} + +int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md, unsigned int *size) { + (void)EVP_DigestFinal_ex(ctx, md, size); + EVP_MD_CTX_cleanup(ctx); + return 1; +} + +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; +} + +size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx) { + return EVP_MD_size(EVP_MD_CTX_md(ctx)); +} + +size_t 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)); +} + +int EVP_add_digest(const EVP_MD *digest) { + return 1; +} diff --git a/external/boringssl/crypto/digest/digest_test.cc b/external/boringssl/crypto/digest/digest_test.cc new file mode 100644 index 0000000000..39ceaffcd8 --- /dev/null +++ b/external/boringssl/crypto/digest/digest_test.cc @@ -0,0 +1,262 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +struct MD { + // name is the name of the digest. + const char* name; + // md_func is the digest to test. + const EVP_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 *); +}; + +static const MD md4 = { "MD4", &EVP_md4, nullptr }; +static const MD md5 = { "MD5", &EVP_md5, &MD5 }; +static const MD sha1 = { "SHA1", &EVP_sha1, &SHA1 }; +static const MD sha224 = { "SHA224", &EVP_sha224, &SHA224 }; +static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256 }; +static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384 }; +static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512 }; +static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr }; + +struct TestVector { + // md is the digest to test. + const MD &md; + // 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; +}; + +static const TestVector kTestVectors[] = { + // MD4 tests, from RFC 1320. (crypto/md4 does not provide a + // one-shot MD4 function.) + { md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" }, + { md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" }, + { md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" }, + { md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b" }, + { md4, "abcdefghijklmnopqrstuvwxyz", 1, + "d79e1c308aa5bbcdeea8ed63df412da9" }, + { md4, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1, + "043f8582f241db351ce627e153e7f0e4" }, + { md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" }, + + // MD5 tests, from RFC 1321. + { md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" }, + { md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" }, + { md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" }, + { md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" }, + { md5, "abcdefghijklmnopqrstuvwxyz", 1, + "c3fcd3d76192e4007dfb496cca67e13b" }, + { md5, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1, + "d174ab98d277d9f5a5611c2c9f419d9f" }, + { md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" }, + + // SHA-1 tests, from RFC 3174. + { sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" }, + { sha1, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, + "84983e441c3bd26ebaae4aa1f95129e5e54670f1" }, + { sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f" }, + { sha1, + "0123456701234567012345670123456701234567012345670123456701234567", 10, + "dea356a2cddd90c7a7ecedc5ebb563934f460452" }, + + // SHA-224 tests, from RFC 3874. + { sha224, "abc", 1, + "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" }, + { sha224, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, + "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" }, + { sha224, + "a", 1000000, + "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" }, + + // SHA-256 tests, from NIST. + { sha256, "abc", 1, + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" }, + { sha256, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" }, + + // SHA-384 tests, from NIST. + { sha384, "abc", 1, + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" + "8086072ba1e7cc2358baeca134c825a7" }, + { sha384, + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1, + "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712" + "fcc7c71a557e2db966c3e9fa91746039" }, + + // SHA-512 tests, from NIST. + { sha512, "abc", 1, + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" }, + { sha512, + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1, + "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" }, + + // MD5-SHA1 tests. + { md5_sha1, "abc", 1, + "900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" }, +}; + +static bool CompareDigest(const TestVector *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", + test->md.name, test->input, (int)test->repeat, + digest_hex, test->expected_hex); + return false; + } + + return true; +} + +static int TestDigest(const TestVector *test) { + ScopedEVP_MD_CTX ctx; + + // Test the input provided. + if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) { + fprintf(stderr, "EVP_DigestInit_ex failed\n"); + return false; + } + for (size_t i = 0; i < test->repeat; i++) { + if (!EVP_DigestUpdate(ctx.get(), test->input, strlen(test->input))) { + fprintf(stderr, "EVP_DigestUpdate failed\n"); + return false; + } + } + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned digest_len; + if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) { + fprintf(stderr, "EVP_DigestFinal_ex failed\n"); + return false; + } + if (!CompareDigest(test, digest, digest_len)) { + return false; + } + + // Test the input one character at a time. + if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) { + fprintf(stderr, "EVP_DigestInit_ex failed\n"); + return false; + } + if (!EVP_DigestUpdate(ctx.get(), NULL, 0)) { + fprintf(stderr, "EVP_DigestUpdate failed\n"); + return false; + } + for (size_t i = 0; i < test->repeat; i++) { + for (const char *p = test->input; *p; p++) { + if (!EVP_DigestUpdate(ctx.get(), p, 1)) { + fprintf(stderr, "EVP_DigestUpdate failed\n"); + return false; + } + } + } + if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) { + fprintf(stderr, "EVP_DigestFinal_ex failed\n"); + return false; + } + if (digest_len != EVP_MD_size(test->md.func())) { + fprintf(stderr, "EVP_MD_size output incorrect\n"); + return false; + } + if (!CompareDigest(test, digest, digest_len)) { + return false; + } + + // Test the one-shot function. + if (test->md.one_shot_func && test->repeat == 1) { + uint8_t *out = test->md.one_shot_func((const uint8_t *)test->input, + strlen(test->input), digest); + if (out != digest) { + fprintf(stderr, "one_shot_func gave incorrect return\n"); + return false; + } + if (!CompareDigest(test, digest, EVP_MD_size(test->md.func()))) { + return false; + } + + // Test the deprecated static buffer variant, until it's removed. + out = test->md.one_shot_func((const uint8_t *)test->input, + strlen(test->input), NULL); + if (!CompareDigest(test, out, EVP_MD_size(test->md.func()))) { + return false; + } + } + + return true; +} + +static int TestGetters() { + if (EVP_get_digestbyname("RSA-SHA512") == NULL || + EVP_get_digestbyname("sha512WithRSAEncryption") == NULL || + EVP_get_digestbyname("nonsense") != NULL) { + return false; + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + for (size_t i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) { + if (!TestDigest(&kTestVectors[i])) { + fprintf(stderr, "Test %d failed\n", (int)i); + return 1; + } + } + + if (!TestGetters()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/digest/digests.c b/external/boringssl/crypto/digest/digests.c new file mode 100644 index 0000000000..3307f2656c --- /dev/null +++ b/external/boringssl/crypto/digest/digests.c @@ -0,0 +1,321 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + +#if defined(NDEBUG) +#define CHECK(x) (void) (x) +#else +#define CHECK(x) assert(x) +#endif + + +static void md4_init(EVP_MD_CTX *ctx) { + CHECK(MD4_Init(ctx->md_data)); +} + +static void md4_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(MD4_Update(ctx->md_data, data, count)); +} + +static void md4_final(EVP_MD_CTX *ctx, uint8_t *out) { + CHECK(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 void md5_init(EVP_MD_CTX *ctx) { + CHECK(MD5_Init(ctx->md_data)); +} + +static void md5_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(MD5_Update(ctx->md_data, data, count)); +} + +static void md5_final(EVP_MD_CTX *ctx, uint8_t *out) { + CHECK(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 void sha1_init(EVP_MD_CTX *ctx) { + CHECK(SHA1_Init(ctx->md_data)); +} + +static void sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA1_Update(ctx->md_data, data, count)); +} + +static void sha1_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(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 void sha224_init(EVP_MD_CTX *ctx) { + CHECK(SHA224_Init(ctx->md_data)); +} + +static void sha224_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA224_Update(ctx->md_data, data, count)); +} + +static void sha224_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(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 void sha256_init(EVP_MD_CTX *ctx) { + CHECK(SHA256_Init(ctx->md_data)); +} + +static void sha256_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA256_Update(ctx->md_data, data, count)); +} + +static void sha256_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(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 void sha384_init(EVP_MD_CTX *ctx) { + CHECK(SHA384_Init(ctx->md_data)); +} + +static void sha384_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA384_Update(ctx->md_data, data, count)); +} + +static void sha384_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(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 void sha512_init(EVP_MD_CTX *ctx) { + CHECK(SHA512_Init(ctx->md_data)); +} + +static void sha512_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA512_Update(ctx->md_data, data, count)); +} + +static void sha512_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(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 void md5_sha1_init(EVP_MD_CTX *md_ctx) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + CHECK(MD5_Init(&ctx->md5) && SHA1_Init(&ctx->sha1)); +} + +static void md5_sha1_update(EVP_MD_CTX *md_ctx, const void *data, + size_t count) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + CHECK(MD5_Update(&ctx->md5, data, count) && + SHA1_Update(&ctx->sha1, data, count)); +} + +static void md5_sha1_final(EVP_MD_CTX *md_ctx, uint8_t *out) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + CHECK(MD5_Final(out, &ctx->md5) && + SHA1_Final(out + MD5_DIGEST_LENGTH, &ctx->sha1)); +} + +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); + const char *short_name; + const char *long_name; +}; + +static const struct nid_to_digest nid_to_digest_mapping[] = { + { NID_md4, EVP_md4, SN_md4, LN_md4 }, + { NID_md5, EVP_md5, SN_md5, LN_md5 }, + { NID_sha1, EVP_sha1, SN_sha1, LN_sha1 }, + { NID_sha224, EVP_sha224, SN_sha224, LN_sha224 }, + { NID_sha256, EVP_sha256, SN_sha256, LN_sha256 }, + { NID_sha384, EVP_sha384, SN_sha384, LN_sha384 }, + { NID_sha512, EVP_sha512, SN_sha512, LN_sha512 }, + { NID_md5_sha1, EVP_md5_sha1, SN_md5_sha1, LN_md5_sha1 }, + { NID_dsaWithSHA, EVP_sha1, SN_dsaWithSHA, LN_dsaWithSHA }, + { NID_dsaWithSHA1, EVP_sha1, SN_dsaWithSHA1, LN_dsaWithSHA1 }, + { NID_ecdsa_with_SHA1, EVP_sha1, SN_ecdsa_with_SHA1, NULL }, + { NID_md5WithRSAEncryption, EVP_md5, SN_md5WithRSAEncryption, + LN_md5WithRSAEncryption }, + { NID_sha1WithRSAEncryption, EVP_sha1, SN_sha1WithRSAEncryption, + LN_sha1WithRSAEncryption }, + { NID_sha224WithRSAEncryption, EVP_sha224, SN_sha224WithRSAEncryption, + LN_sha224WithRSAEncryption }, + { NID_sha256WithRSAEncryption, EVP_sha256, SN_sha256WithRSAEncryption, + LN_sha256WithRSAEncryption }, + { NID_sha384WithRSAEncryption, EVP_sha384, SN_sha384WithRSAEncryption, + LN_sha384WithRSAEncryption }, + { NID_sha512WithRSAEncryption, EVP_sha512, SN_sha512WithRSAEncryption, + LN_sha512WithRSAEncryption }, +}; + +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)); +} + +const EVP_MD *EVP_get_digestbyname(const char *name) { + unsigned i; + + for (i = 0; i < sizeof(nid_to_digest_mapping) / sizeof(struct nid_to_digest); + i++) { + const char *short_name = nid_to_digest_mapping[i].short_name; + const char *long_name = nid_to_digest_mapping[i].long_name; + if ((short_name && strcmp(short_name, name) == 0) || + (long_name && strcmp(long_name, name) == 0)) { + return nid_to_digest_mapping[i].md_func(); + } + } + + return NULL; +} diff --git a/external/boringssl/crypto/digest/internal.h b/external/boringssl/crypto/digest/internal.h new file mode 100644 index 0000000000..e3d812ad8c --- /dev/null +++ b/external/boringssl/crypto/digest/internal.h @@ -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.] */ + +#ifndef OPENSSL_HEADER_DIGEST_INTERNAL_H +#define OPENSSL_HEADER_DIGEST_INTERNAL_H + +#include + +#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|. */ + void (*init)(EVP_MD_CTX *ctx); + + /* update hashes |len| bytes of |data| into the state in |ctx->md_data|. */ + void (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); + + /* final completes the hash and writes |md_size| bytes of digest to |out|. */ + void (*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 layering 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); +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_DIGEST_INTERNAL */ diff --git a/external/boringssl/crypto/digest/md32_common.h b/external/boringssl/crypto/digest/md32_common.h new file mode 100644 index 0000000000..4cf050caec --- /dev/null +++ b/external/boringssl/crypto/digest/md32_common.h @@ -0,0 +1,262 @@ +/* ==================================================================== + * 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 + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* This is a generic 32-bit "collector" for message digest algorithms. It + * collects input character stream into chunks of 32-bit values and invokes the + * block function that performs the actual hash calculations. To make use of + * this mechanism, the following macros must be defined before including + * md32_common.h. + * + * One of |DATA_ORDER_IS_BIG_ENDIAN| or |DATA_ORDER_IS_LITTLE_ENDIAN| must be + * defined to specify the byte order of the input stream. + * + * |HASH_CBLOCK| must be defined as the integer block size, in bytes. + * + * |HASH_CTX| must be defined as the name of the context structure, which must + * have at least the following members: + * + * typedef struct _state_st { + * uint32_t h[ / sizeof(uint32_t)]; + * uint32_t Nl, Nh; + * uint8_t data[HASH_CBLOCK]; + * unsigned num; + * ... + * } _CTX; + * + * is the output length of the hash in bytes, before + * any truncation (e.g. 64 for SHA-224 and SHA-256, 128 for SHA-384 and + * SHA-512). + * + * |HASH_UPDATE| must be defined as the name of the "Update" function to + * generate. + * + * |HASH_TRANSFORM| must be defined as the the name of the "Transform" + * function to generate. + * + * |HASH_FINAL| must be defined as the name of "Final" function to generate. + * + * |HASH_BLOCK_DATA_ORDER| must be defined as the name of the "Block" function. + * That function must be implemented manually. It must be capable of operating + * on *unaligned* input data in its original (data) byte order. It must have + * this signature: + * + * void HASH_BLOCK_DATA_ORDER(uint32_t *state, const uint8_t *data, + * size_t num); + * + * It must update the hash state |state| with |num| blocks of data from |data|, + * where each block is |HASH_CBLOCK| bytes; i.e. |data| points to a array of + * |HASH_CBLOCK * num| bytes. |state| points to the |h| member of a |HASH_CTX|, + * and so will have | / sizeof(uint32_t)| elements. + * + * |HASH_MAKE_STRING(c, s)| must be defined as a block statement that converts + * the hash state |c->h| into the output byte order, storing the result in |s|. + */ + +#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_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 + +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#endif + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +#define HOST_c2l(c, l) \ + (void)(l = (((uint32_t)(*((c)++))) << 24), \ + l |= (((uint32_t)(*((c)++))) << 16), \ + l |= (((uint32_t)(*((c)++))) << 8), l |= (((uint32_t)(*((c)++))))) + +#define HOST_l2c(l, c) \ + (void)(*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l)) & 0xff)) + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +#define HOST_c2l(c, l) \ + (void)(l = (((uint32_t)(*((c)++)))), l |= (((uint32_t)(*((c)++))) << 8), \ + l |= (((uint32_t)(*((c)++))) << 16), \ + l |= (((uint32_t)(*((c)++))) << 24)) + +#define HOST_l2c(l, c) \ + (void)(*((c)++) = (uint8_t)(((l)) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 24) & 0xff)) + +#endif /* DATA_ORDER */ + +int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) { + const uint8_t *data = data_; + + if (len == 0) { + return 1; + } + + uint32_t l = c->Nl + (((uint32_t)len) << 3); + if (l < c->Nl) { + /* Handle carries. */ + c->Nh++; + } + c->Nh += (uint32_t)(len >> 29); + c->Nl = l; + + size_t n = c->num; + if (n != 0) { + if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) { + memcpy(c->data + n, data, HASH_CBLOCK - n); + HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); + n = HASH_CBLOCK - n; + data += n; + len -= n; + c->num = 0; + /* Keep |c->data| zeroed when unused. */ + memset(c->data, 0, HASH_CBLOCK); + } else { + memcpy(c->data + n, data, len); + c->num += (unsigned)len; + return 1; + } + } + + n = len / HASH_CBLOCK; + if (n > 0) { + HASH_BLOCK_DATA_ORDER(c->h, data, n); + n *= HASH_CBLOCK; + data += n; + len -= n; + } + + if (len != 0) { + c->num = (unsigned)len; + memcpy(c->data, data, len); + } + return 1; +} + + +void HASH_TRANSFORM(HASH_CTX *c, const uint8_t *data) { + HASH_BLOCK_DATA_ORDER(c->h, data, 1); +} + + +int HASH_FINAL(uint8_t *md, HASH_CTX *c) { + /* |c->data| always has room for at least one byte. A full block would have + * been consumed. */ + size_t n = c->num; + assert(n < HASH_CBLOCK); + c->data[n] = 0x80; + n++; + + /* Fill the block with zeros if there isn't room for a 64-bit length. */ + if (n > (HASH_CBLOCK - 8)) { + memset(c->data + n, 0, HASH_CBLOCK - n); + n = 0; + HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); + } + memset(c->data + n, 0, HASH_CBLOCK - 8 - n); + + /* Append a 64-bit length to the block and process it. */ + uint8_t *p = c->data + HASH_CBLOCK - 8; +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + HOST_l2c(c->Nh, p); + HOST_l2c(c->Nl, p); +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + HOST_l2c(c->Nl, p); + HOST_l2c(c->Nh, p); +#endif + assert(p == c->data + HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); + c->num = 0; + memset(c->data, 0, HASH_CBLOCK); + + HASH_MAKE_STRING(c, md); + return 1; +} + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_MD32_COMMON_H */ diff --git a/external/boringssl/crypto/dsa/CMakeLists.txt b/external/boringssl/crypto/dsa/CMakeLists.txt new file mode 100644 index 0000000000..3cb7c349b1 --- /dev/null +++ b/external/boringssl/crypto/dsa/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + dsa + + OBJECT + + dsa.c + dsa_asn1.c +) + +if(ENABLE_TESTS) +add_executable( + dsa_test + + dsa_test.c + + $ +) + +target_link_libraries(dsa_test crypto) +add_dependencies(all_tests dsa_test) +endif() diff --git a/external/boringssl/crypto/dsa/dsa.c b/external/boringssl/crypto/dsa/dsa.c new file mode 100644 index 0000000000..1de0071e38 --- /dev/null +++ b/external/boringssl/crypto/dsa/dsa.c @@ -0,0 +1,933 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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 . */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +DSA *DSA_new(void) { + DSA *dsa = OPENSSL_malloc(sizeof(DSA)); + if (dsa == NULL) { + OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(dsa, 0, sizeof(DSA)); + + dsa->references = 1; + + CRYPTO_MUTEX_init(&dsa->method_mont_p_lock); + CRYPTO_new_ex_data(&dsa->ex_data); + + return dsa; +} + +void DSA_free(DSA *dsa) { + if (dsa == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&dsa->references)) { + return; + } + + CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data); + + BN_clear_free(dsa->p); + BN_clear_free(dsa->q); + BN_clear_free(dsa->g); + BN_clear_free(dsa->pub_key); + BN_clear_free(dsa->priv_key); + BN_clear_free(dsa->kinv); + BN_clear_free(dsa->r); + BN_MONT_CTX_free(dsa->method_mont_p); + CRYPTO_MUTEX_cleanup(&dsa->method_mont_p_lock); + OPENSSL_free(dsa); +} + +int DSA_up_ref(DSA *dsa) { + CRYPTO_refcount_inc(&dsa->references); + 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) { + 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 qsize; + const EVP_MD *evpmd; + + evpmd = (bits >= 2048) ? EVP_sha256() : EVP_sha1(); + qsize = EVP_MD_size(evpmd); + + if (bits < 512) { + bits = 512; + } + + bits = (bits + 63) / 64 * 64; + + if (seed_in != NULL) { + if (seed_len < (size_t)qsize) { + return 0; + } + if (seed_len > (size_t)qsize) { + /* Only consume as much seed as is expected. */ + seed_len = qsize; + } + memcpy(seed, seed_in, seed_len); + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + + mont = BN_MONT_CTX_new(); + if (mont == NULL) { + goto err; + } + + r0 = BN_CTX_get(ctx); + g = BN_CTX_get(ctx); + W = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + c = BN_CTX_get(ctx); + p = BN_CTX_get(ctx); + test = BN_CTX_get(ctx); + + if (test == NULL || !BN_lshift(test, BN_value_one(), bits - 1)) { + goto err; + } + + for (;;) { + /* Find q. */ + for (;;) { + /* step 1 */ + if (!BN_GENCB_call(cb, 0, m++)) { + goto err; + } + + int use_random_seed = (seed_in == NULL); + if (use_random_seed) { + if (!RAND_bytes(seed, qsize)) { + goto err; + } + } else { + /* If we come back through, use random seed next time. */ + seed_in = NULL; + } + memcpy(buf, seed, qsize); + memcpy(buf2, seed, qsize); + /* precompute "SEED + 1" for step 7: */ + for (i = qsize - 1; i < 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, use_random_seed, cb); + if (r > 0) { + break; + } + if (r != 0) { + goto err; + } + + /* do a callback call */ + /* step 5 */ + } + + if (!BN_GENCB_call(cb, 2, 0) || !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) { + BN_free(dsa->p); + BN_free(dsa->q); + BN_free(dsa->g); + dsa->p = BN_dup(p); + dsa->q = BN_dup(q); + dsa->g = BN_dup(g); + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + ok = 0; + goto err; + } + if (out_counter != NULL) { + *out_counter = counter; + } + if (out_h != NULL) { + *out_h = h; + } + } + + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + + BN_MONT_CTX_free(mont); + + return ok; +} + +DSA *DSAparams_dup(const DSA *dsa) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + ret->p = BN_dup(dsa->p); + ret->q = BN_dup(dsa->q); + ret->g = BN_dup(dsa->g); + if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_generate_key(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 (dsa->pub_key == NULL) { + BN_free(pub_key); + } + if (dsa->priv_key == NULL) { + BN_free(priv_key); + } + BN_CTX_free(ctx); + + return ok; +} + +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; + } + + BN_free(sig->r); + BN_free(sig->s); + OPENSSL_free(sig); +} + +DSA_SIG *DSA_do_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; + } + + /* 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 = DSA_SIG_new(); + if (ret == NULL) { + goto err; + } + ret->r = r; + ret->s = s; + +err: + if (ret == NULL) { + OPENSSL_PUT_ERROR(DSA, reason); + BN_free(r); + BN_free(s); + } + BN_CTX_free(ctx); + BN_clear_free(&m); + BN_clear_free(&xr); + BN_clear_free(kinv); + + return ret; +} + +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) { + BN_CTX *ctx; + BIGNUM u1, u2, t1; + int ret = 0; + unsigned i; + + *out_valid = 0; + + if (!dsa->p || !dsa->q || !dsa->g) { + OPENSSL_PUT_ERROR(DSA, 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, DSA_R_BAD_Q_VALUE); + return 0; + } + + if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DSA, 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(digest, 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; + } + + if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p, + ctx)) { + goto err; + } + + if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, + dsa->method_mont_p)) { + 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, ERR_R_BN_LIB); + } + BN_CTX_free(ctx); + BN_free(&u1); + BN_free(&u2); + BN_free(&t1); + + return ret; +} + +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: + OPENSSL_free(der); + DSA_SIG_free(s); + return ret; +} + +/* der_len_len returns the number of bytes needed to represent a length of |len| + * in DER. */ +static size_t der_len_len(size_t len) { + if (len < 0x80) { + return 1; + } + size_t ret = 1; + while (len > 0) { + ret++; + len >>= 8; + } + return ret; +} + +int DSA_size(const DSA *dsa) { + size_t order_len = BN_num_bytes(dsa->q); + /* Compute the maximum length of an |order_len| byte integer. Defensively + * assume that the leading 0x00 is included. */ + size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len; + if (integer_len < order_len) { + return 0; + } + /* A DSA signature is two INTEGERs. */ + size_t value_len = 2 * integer_len; + if (value_len < integer_len) { + return 0; + } + /* Add the header. */ + size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len; + if (ret < value_len) { + return 0; + } + return ret; +} + +int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, + BIGNUM **out_r) { + 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, 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 (!BN_rand_range(&k, dsa->q)) { + 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_MUTEX *)&dsa->method_mont_p_lock, 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) && !BN_add(&kq, &kq, dsa->q)) { + goto err; + } + + BN_set_flags(&kq, BN_FLG_CONSTTIME); + 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; + } + + BN_clear_free(*out_kinv); + *out_kinv = kinv; + kinv = NULL; + BN_clear_free(*out_r); + *out_r = r; + ret = 1; + +err: + if (!ret) { + OPENSSL_PUT_ERROR(DSA, 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; +} + +int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +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: + DH_free(ret); + return NULL; +} diff --git a/external/boringssl/crypto/dsa/dsa_asn1.c b/external/boringssl/crypto/dsa/dsa_asn1.c new file mode 100644 index 0000000000..ff5ee0039c --- /dev/null +++ b/external/boringssl/crypto/dsa/dsa_asn1.c @@ -0,0 +1,339 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include + +#include "../bytestring/internal.h" + + +static int parse_integer(CBS *cbs, BIGNUM **out) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + return BN_parse_asn1_unsigned(cbs, *out); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* A DSA object may be missing some components. */ + OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return BN_marshal_asn1(cbb, bn); +} + +DSA_SIG *DSA_SIG_parse(CBS *cbs) { + DSA_SIG *ret = DSA_SIG_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->r) || + !parse_integer(&child, &ret->s) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_SIG_free(ret); + return NULL; + } + return ret; +} + +int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, sig->r) || + !marshal_integer(&child, sig->s) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_public_key(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->pub_key) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dsa->pub_key) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_parameters(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_private_key(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + uint64_t version; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&child, &version)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + goto err; + } + + if (version != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION); + goto err; + } + + if (!parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + !parse_integer(&child, &ret->pub_key) || + !parse_integer(&child, &ret->priv_key) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + goto err; + } + return ret; + +err: + DSA_free(ret); + return NULL; +} + +int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&child, 0 /* version */) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !marshal_integer(&child, dsa->pub_key) || + !marshal_integer(&child, dsa->priv_key) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA_SIG *ret = DSA_SIG_parse(&cbs); + if (ret == NULL) { + return NULL; + } + if (out_sig != NULL) { + DSA_SIG_free(*out_sig); + *out_sig = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_SIG_marshal(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_public_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_public_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_private_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_parameters(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAparams(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_parameters(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} diff --git a/external/boringssl/crypto/dsa/dsa_test.c b/external/boringssl/crypto/dsa/dsa_test.c new file mode 100644 index 0000000000..6296c8f06e --- /dev/null +++ b/external/boringssl/crypto/dsa/dsa_test.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.] + * + * The DSS routines are based on patches supplied by + * Steven Schoch . */ + +#include + +#include + +#include +#include +#include + + +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 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(FILE *out) { + 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; + + fprintf(out, "test generation of DSA parameters\n"); + + BN_GENCB_set(&cb, dsa_cb, out); + dsa = DSA_new(); + if (dsa == NULL || + !DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) { + goto end; + } + + fprintf(out, "seed\n"); + for (i = 0; i < 20; i += 4) { + fprintf(out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2], + seed[i + 3]); + } + fprintf(out, "\ncounter=%d h=%ld\n", counter, h); + + if (counter != 105) { + fprintf(stderr, "counter should be 105\n"); + goto end; + } + if (h != 2) { + fprintf(stderr, "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) { + fprintf(stderr, "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) { + fprintf(stderr, "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) { + fprintf(stderr, "g value is wrong\n"); + goto end; + } + + if (!DSA_generate_key(dsa) || + !DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa)) { + goto end; + } + if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) { + ok = 1; + } else { + fprintf(stderr, "verification failure\n"); + } + +end: + 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) { + fprintf(stderr, "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: + DSA_free(dsa); + + return ok; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (!test_generate(stdout) || + !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)) { + ERR_print_errors_fp(stderr); + return 1; + } + + 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'; + } + + fputc(c, arg->arg); + fflush(arg->arg); + + if (!ok && p == 0 && num > 1) { + fprintf(stderr, "error in dsatest\n"); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/ec/CMakeLists.txt b/external/boringssl/crypto/ec/CMakeLists.txt new file mode 100644 index 0000000000..0d429e0bef --- /dev/null +++ b/external/boringssl/crypto/ec/CMakeLists.txt @@ -0,0 +1,53 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + EC_ARCH_SOURCES + + p256-x86_64-asm.${ASM_EXT} + ) +endif() + +add_library( + ec + + OBJECT + + ec.c + ec_asn1.c + ec_key.c + ec_montgomery.c + oct.c + p224-64.c + p256-64.c + p256-x86_64.c + simple.c + util-64.c + wnaf.c + + ${EC_ARCH_SOURCES} +) + +perlasm(p256-x86_64-asm.${ASM_EXT} asm/p256-x86_64-asm.pl) + +if(ENABLE_TESTS) +add_executable( + example_mul + + example_mul.c + + $ +) + +add_executable( + ec_test + + ec_test.cc + + $ +) + +target_link_libraries(example_mul crypto) +target_link_libraries(ec_test crypto) +add_dependencies(all_tests example_mul ec_test) +endif() diff --git a/external/boringssl/crypto/ec/asm/p256-x86_64-asm.pl b/external/boringssl/crypto/ec/asm/p256-x86_64-asm.pl new file mode 100755 index 0000000000..50a5fe6ee9 --- /dev/null +++ b/external/boringssl/crypto/ec/asm/p256-x86_64-asm.pl @@ -0,0 +1,2734 @@ +#!/usr/bin/env perl + +# Copyright (c) 2014, Intel Corporation. +# +# 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. + +# Developers and authors: +# Shay Gueron (1, 2), and Vlad Krasnov (1) +# (1) Intel Corporation, Israel Development Center +# (2) University of Haifa + +# Reference: +# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with +# 256 Bit Primes" + +# Further optimization by : +# +# this/original +# Opteron +12-49% +# Bulldozer +14-45% +# P4 +18-46% +# Westmere +12-34% +# Sandy Bridge +9-35% +# Ivy Bridge +9-35% +# Haswell +8-37% +# Broadwell +18-58% +# Atom +15-50% +# VIA Nano +43-160% +# +# Ranges denote minimum and maximum improvement coefficients depending +# on benchmark. + +$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; + +# TODO: enable these after testing. $avx goes to two and $addx to one. +$avx=0; +$addx=0; + +$code.=<<___; +.text +.extern OPENSSL_ia32cap_P + +# The polynomial +.align 64 +.Lpoly: +.quad 0xffffffffffffffff, 0x00000000ffffffff, 0x0000000000000000, 0xffffffff00000001 + +.LOne: +.long 1,1,1,1,1,1,1,1 +.LTwo: +.long 2,2,2,2,2,2,2,2 +.LThree: +.long 3,3,3,3,3,3,3,3 +.LONE_mont: +.quad 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe +___ + +{ +################################################################################ +# void ecp_nistz256_mul_by_2(uint64_t res[4], uint64_t a[4]); + +my ($a0,$a1,$a2,$a3)=map("%r$_",(8..11)); +my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rdx","%rcx","%r12","%r13"); +my ($r_ptr,$a_ptr,$b_ptr)=("%rdi","%rsi","%rdx"); + +$code.=<<___; + +.type ecp_nistz256_mul_by_2,\@function,2 +.align 64 +ecp_nistz256_mul_by_2: + push %r12 + push %r13 + + mov 8*0($a_ptr), $a0 + mov 8*1($a_ptr), $a1 + add $a0, $a0 # a0:a3+a0:a3 + mov 8*2($a_ptr), $a2 + adc $a1, $a1 + mov 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + sbb $t4, $t4 + + sub 8*0($a_ptr), $a0 + mov $a2, $t2 + sbb 8*1($a_ptr), $a1 + sbb 8*2($a_ptr), $a2 + mov $a3, $t3 + sbb 8*3($a_ptr), $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + pop %r13 + pop %r12 + ret +.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 + +################################################################################ +# void ecp_nistz256_neg(uint64_t res[4], uint64_t a[4]); +.globl ecp_nistz256_neg +.type ecp_nistz256_neg,\@function,2 +.align 32 +ecp_nistz256_neg: + push %r12 + push %r13 + + xor $a0, $a0 + xor $a1, $a1 + xor $a2, $a2 + xor $a3, $a3 + xor $t4, $t4 + + sub 8*0($a_ptr), $a0 + sbb 8*1($a_ptr), $a1 + sbb 8*2($a_ptr), $a2 + mov $a0, $t0 + sbb 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + mov $a1, $t1 + sbb \$0, $t4 + + add 8*0($a_ptr), $a0 + mov $a2, $t2 + adc 8*1($a_ptr), $a1 + adc 8*2($a_ptr), $a2 + mov $a3, $t3 + adc 8*3($a_ptr), $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + pop %r13 + pop %r12 + ret +.size ecp_nistz256_neg,.-ecp_nistz256_neg +___ +} +{ +my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx"); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15)); +my ($t0,$t1,$t2,$t3,$t4)=("%rcx","%rbp","%rbx","%rdx","%rax"); +my ($poly1,$poly3)=($acc6,$acc7); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_mul_mont( +# uint64_t res[4], +# uint64_t a[4], +# uint64_t b[4]); + +.globl ecp_nistz256_mul_mont +.type ecp_nistz256_mul_mont,\@function,3 +.align 32 +ecp_nistz256_mul_mont: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx +___ +$code.=<<___; +.Lmul_mont: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 +___ +$code.=<<___ if ($addx); + cmp \$0x80100, %ecx + je .Lmul_montx +___ +$code.=<<___; + mov $b_org, $b_ptr + mov 8*0($b_org), %rax + mov 8*0($a_ptr), $acc1 + mov 8*1($a_ptr), $acc2 + mov 8*2($a_ptr), $acc3 + mov 8*3($a_ptr), $acc4 + + call __ecp_nistz256_mul_montq +___ +$code.=<<___ if ($addx); + jmp .Lmul_mont_done + +.align 32 +.Lmul_montx: + mov $b_org, $b_ptr + mov 8*0($b_org), %rdx + mov 8*0($a_ptr), $acc1 + mov 8*1($a_ptr), $acc2 + mov 8*2($a_ptr), $acc3 + mov 8*3($a_ptr), $acc4 + lea -128($a_ptr), $a_ptr # control u-op density + + call __ecp_nistz256_mul_montx +___ +$code.=<<___; +.Lmul_mont_done: + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont + +.type __ecp_nistz256_mul_montq,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_montq: + ######################################################################## + # Multiply a by b[0] + mov %rax, $t1 + mulq $acc1 + mov .Lpoly+8*1(%rip),$poly1 + mov %rax, $acc0 + mov $t1, %rax + mov %rdx, $acc1 + + mulq $acc2 + mov .Lpoly+8*3(%rip),$poly3 + add %rax, $acc1 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $acc2 + + mulq $acc3 + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $acc3 + + mulq $acc4 + add %rax, $acc3 + mov $acc0, %rax + adc \$0, %rdx + xor $acc5, $acc5 + mov %rdx, $acc4 + + ######################################################################## + # First reduction step + # Basically now we want to multiply acc[0] by p256, + # and add the result to the acc. + # Due to the special form of p256 we do some optimizations + # + # acc[0] x p256[0..1] = acc[0] x 2^96 - acc[0] + # then we add acc[0] and get acc[0] x 2^96 + + mov $acc0, $t1 + shl \$32, $acc0 + mulq $poly3 + shr \$32, $t1 + add $acc0, $acc1 # +=acc[0]<<96 + adc $t1, $acc2 + adc %rax, $acc3 + mov 8*1($b_ptr), %rax + adc %rdx, $acc4 + adc \$0, $acc5 + xor $acc0, $acc0 + + ######################################################################## + # Multiply by b[1] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc1 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc2 + adc \$0, %rdx + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $acc1, %rax + adc %rdx, $acc5 + adc \$0, $acc0 + + ######################################################################## + # Second reduction step + mov $acc1, $t1 + shl \$32, $acc1 + mulq $poly3 + shr \$32, $t1 + add $acc1, $acc2 + adc $t1, $acc3 + adc %rax, $acc4 + mov 8*2($b_ptr), %rax + adc %rdx, $acc5 + adc \$0, $acc0 + xor $acc1, $acc1 + + ######################################################################## + # Multiply by b[2] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc5 + adc \$0, %rdx + add %rax, $acc5 + mov $acc2, %rax + adc %rdx, $acc0 + adc \$0, $acc1 + + ######################################################################## + # Third reduction step + mov $acc2, $t1 + shl \$32, $acc2 + mulq $poly3 + shr \$32, $t1 + add $acc2, $acc3 + adc $t1, $acc4 + adc %rax, $acc5 + mov 8*3($b_ptr), %rax + adc %rdx, $acc0 + adc \$0, $acc1 + xor $acc2, $acc2 + + ######################################################################## + # Multiply by b[3] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc5 + adc \$0, %rdx + add %rax, $acc5 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc0 + adc \$0, %rdx + add %rax, $acc0 + mov $acc3, %rax + adc %rdx, $acc1 + adc \$0, $acc2 + + ######################################################################## + # Final reduction step + mov $acc3, $t1 + shl \$32, $acc3 + mulq $poly3 + shr \$32, $t1 + add $acc3, $acc4 + adc $t1, $acc5 + mov $acc4, $t0 + adc %rax, $acc0 + adc %rdx, $acc1 + mov $acc5, $t1 + adc \$0, $acc2 + + ######################################################################## + # Branch-less conditional subtraction of P + sub \$-1, $acc4 # .Lpoly[0] + mov $acc0, $t2 + sbb $poly1, $acc5 # .Lpoly[1] + sbb \$0, $acc0 # .Lpoly[2] + mov $acc1, $t3 + sbb $poly3, $acc1 # .Lpoly[3] + sbb \$0, $acc2 + + cmovc $t0, $acc4 + cmovc $t1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $t2, $acc0 + mov $acc5, 8*1($r_ptr) + cmovc $t3, $acc1 + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_montq,.-__ecp_nistz256_mul_montq + +################################################################################ +# void ecp_nistz256_sqr_mont( +# uint64_t res[4], +# uint64_t a[4]); + +# we optimize the square according to S.Gueron and V.Krasnov, +# "Speeding up Big-Number Squaring" +.globl ecp_nistz256_sqr_mont +.type ecp_nistz256_sqr_mont,\@function,2 +.align 32 +ecp_nistz256_sqr_mont: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx +___ +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 +___ +$code.=<<___ if ($addx); + cmp \$0x80100, %ecx + je .Lsqr_montx +___ +$code.=<<___; + mov 8*0($a_ptr), %rax + mov 8*1($a_ptr), $acc6 + mov 8*2($a_ptr), $acc7 + mov 8*3($a_ptr), $acc0 + + call __ecp_nistz256_sqr_montq +___ +$code.=<<___ if ($addx); + jmp .Lsqr_mont_done + +.align 32 +.Lsqr_montx: + mov 8*0($a_ptr), %rdx + mov 8*1($a_ptr), $acc6 + mov 8*2($a_ptr), $acc7 + mov 8*3($a_ptr), $acc0 + lea -128($a_ptr), $a_ptr # control u-op density + + call __ecp_nistz256_sqr_montx +___ +$code.=<<___; +.Lsqr_mont_done: + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont + +.type __ecp_nistz256_sqr_montq,\@abi-omnipotent +.align 32 +__ecp_nistz256_sqr_montq: + mov %rax, $acc5 + mulq $acc6 # a[1]*a[0] + mov %rax, $acc1 + mov $acc7, %rax + mov %rdx, $acc2 + + mulq $acc5 # a[0]*a[2] + add %rax, $acc2 + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $acc3 + + mulq $acc5 # a[0]*a[3] + add %rax, $acc3 + mov $acc7, %rax + adc \$0, %rdx + mov %rdx, $acc4 + + ################################# + mulq $acc6 # a[1]*a[2] + add %rax, $acc3 + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq $acc6 # a[1]*a[3] + add %rax, $acc4 + mov $acc0, %rax + adc \$0, %rdx + add $t1, $acc4 + mov %rdx, $acc5 + adc \$0, $acc5 + + ################################# + mulq $acc7 # a[2]*a[3] + xor $acc7, $acc7 + add %rax, $acc5 + mov 8*0($a_ptr), %rax + mov %rdx, $acc6 + adc \$0, $acc6 + + add $acc1, $acc1 # acc1:6<<1 + adc $acc2, $acc2 + adc $acc3, $acc3 + adc $acc4, $acc4 + adc $acc5, $acc5 + adc $acc6, $acc6 + adc \$0, $acc7 + + mulq %rax + mov %rax, $acc0 + mov 8*1($a_ptr), %rax + mov %rdx, $t0 + + mulq %rax + add $t0, $acc1 + adc %rax, $acc2 + mov 8*2($a_ptr), %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq %rax + add $t0, $acc3 + adc %rax, $acc4 + mov 8*3($a_ptr), %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq %rax + add $t0, $acc5 + adc %rax, $acc6 + mov $acc0, %rax + adc %rdx, $acc7 + + mov .Lpoly+8*1(%rip), $a_ptr + mov .Lpoly+8*3(%rip), $t1 + + ########################################## + # Now the reduction + # First iteration + mov $acc0, $t0 + shl \$32, $acc0 + mulq $t1 + shr \$32, $t0 + add $acc0, $acc1 # +=acc[0]<<96 + adc $t0, $acc2 + adc %rax, $acc3 + mov $acc1, %rax + adc \$0, %rdx + + ########################################## + # Second iteration + mov $acc1, $t0 + shl \$32, $acc1 + mov %rdx, $acc0 + mulq $t1 + shr \$32, $t0 + add $acc1, $acc2 + adc $t0, $acc3 + adc %rax, $acc0 + mov $acc2, %rax + adc \$0, %rdx + + ########################################## + # Third iteration + mov $acc2, $t0 + shl \$32, $acc2 + mov %rdx, $acc1 + mulq $t1 + shr \$32, $t0 + add $acc2, $acc3 + adc $t0, $acc0 + adc %rax, $acc1 + mov $acc3, %rax + adc \$0, %rdx + + ########################################### + # Last iteration + mov $acc3, $t0 + shl \$32, $acc3 + mov %rdx, $acc2 + mulq $t1 + shr \$32, $t0 + add $acc3, $acc0 + adc $t0, $acc1 + adc %rax, $acc2 + adc \$0, %rdx + xor $acc3, $acc3 + + ############################################ + # Add the rest of the acc + add $acc0, $acc4 + adc $acc1, $acc5 + mov $acc4, $acc0 + adc $acc2, $acc6 + adc %rdx, $acc7 + mov $acc5, $acc1 + adc \$0, $acc3 + + sub \$-1, $acc4 # .Lpoly[0] + mov $acc6, $acc2 + sbb $a_ptr, $acc5 # .Lpoly[1] + sbb \$0, $acc6 # .Lpoly[2] + mov $acc7, $t0 + sbb $t1, $acc7 # .Lpoly[3] + sbb \$0, $acc3 + + cmovc $acc0, $acc4 + cmovc $acc1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $acc2, $acc6 + mov $acc5, 8*1($r_ptr) + cmovc $t0, $acc7 + mov $acc6, 8*2($r_ptr) + mov $acc7, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sqr_montq,.-__ecp_nistz256_sqr_montq +___ + +if ($addx) { +$code.=<<___; +.type __ecp_nistz256_mul_montx,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_montx: + ######################################################################## + # Multiply by b[0] + mulx $acc1, $acc0, $acc1 + mulx $acc2, $t0, $acc2 + mov \$32, $poly1 + xor $acc5, $acc5 # cf=0 + mulx $acc3, $t1, $acc3 + mov .Lpoly+8*3(%rip), $poly3 + adc $t0, $acc1 + mulx $acc4, $t0, $acc4 + mov $acc0, %rdx + adc $t1, $acc2 + shlx $poly1,$acc0,$t1 + adc $t0, $acc3 + shrx $poly1,$acc0,$t0 + adc \$0, $acc4 + + ######################################################################## + # First reduction step + add $t1, $acc1 + adc $t0, $acc2 + + mulx $poly3, $t0, $t1 + mov 8*1($b_ptr), %rdx + adc $t0, $acc3 + adc $t1, $acc4 + adc \$0, $acc5 + xor $acc0, $acc0 # $acc0=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[1] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc1 + adox $t1, $acc2 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc1, %rdx + adcx $t0, $acc4 + shlx $poly1, $acc1, $t0 + adox $t1, $acc5 + shrx $poly1, $acc1, $t1 + + adcx $acc0, $acc5 + adox $acc0, $acc0 + adc \$0, $acc0 + + ######################################################################## + # Second reduction step + add $t0, $acc2 + adc $t1, $acc3 + + mulx $poly3, $t0, $t1 + mov 8*2($b_ptr), %rdx + adc $t0, $acc4 + adc $t1, $acc5 + adc \$0, $acc0 + xor $acc1 ,$acc1 # $acc1=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[2] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc2, %rdx + adcx $t0, $acc5 + shlx $poly1, $acc2, $t0 + adox $t1, $acc0 + shrx $poly1, $acc2, $t1 + + adcx $acc1, $acc0 + adox $acc1, $acc1 + adc \$0, $acc1 + + ######################################################################## + # Third reduction step + add $t0, $acc3 + adc $t1, $acc4 + + mulx $poly3, $t0, $t1 + mov 8*3($b_ptr), %rdx + adc $t0, $acc5 + adc $t1, $acc0 + adc \$0, $acc1 + xor $acc2, $acc2 # $acc2=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[3] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc5 + adox $t1, $acc0 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc3, %rdx + adcx $t0, $acc0 + shlx $poly1, $acc3, $t0 + adox $t1, $acc1 + shrx $poly1, $acc3, $t1 + + adcx $acc2, $acc1 + adox $acc2, $acc2 + adc \$0, $acc2 + + ######################################################################## + # Fourth reduction step + add $t0, $acc4 + adc $t1, $acc5 + + mulx $poly3, $t0, $t1 + mov $acc4, $t2 + mov .Lpoly+8*1(%rip), $poly1 + adc $t0, $acc0 + mov $acc5, $t3 + adc $t1, $acc1 + adc \$0, $acc2 + + ######################################################################## + # Branch-less conditional subtraction of P + xor %eax, %eax + mov $acc0, $t0 + sbb \$-1, $acc4 # .Lpoly[0] + sbb $poly1, $acc5 # .Lpoly[1] + sbb \$0, $acc0 # .Lpoly[2] + mov $acc1, $t1 + sbb $poly3, $acc1 # .Lpoly[3] + sbb \$0, $acc2 + + cmovc $t2, $acc4 + cmovc $t3, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $t0, $acc0 + mov $acc5, 8*1($r_ptr) + cmovc $t1, $acc1 + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_montx,.-__ecp_nistz256_mul_montx + +.type __ecp_nistz256_sqr_montx,\@abi-omnipotent +.align 32 +__ecp_nistz256_sqr_montx: + mulx $acc6, $acc1, $acc2 # a[0]*a[1] + mulx $acc7, $t0, $acc3 # a[0]*a[2] + xor %eax, %eax + adc $t0, $acc2 + mulx $acc0, $t1, $acc4 # a[0]*a[3] + mov $acc6, %rdx + adc $t1, $acc3 + adc \$0, $acc4 + xor $acc5, $acc5 # $acc5=0,cf=0,of=0 + + ################################# + mulx $acc7, $t0, $t1 # a[1]*a[2] + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx $acc0, $t0, $t1 # a[1]*a[3] + mov $acc7, %rdx + adcx $t0, $acc4 + adox $t1, $acc5 + adc \$0, $acc5 + + ################################# + mulx $acc0, $t0, $acc6 # a[2]*a[3] + mov 8*0+128($a_ptr), %rdx + xor $acc7, $acc7 # $acc7=0,cf=0,of=0 + adcx $acc1, $acc1 # acc1:6<<1 + adox $t0, $acc5 + adcx $acc2, $acc2 + adox $acc7, $acc6 # of=0 + + mulx %rdx, $acc0, $t1 + mov 8*1+128($a_ptr), %rdx + adcx $acc3, $acc3 + adox $t1, $acc1 + adcx $acc4, $acc4 + mulx %rdx, $t0, $t4 + mov 8*2+128($a_ptr), %rdx + adcx $acc5, $acc5 + adox $t0, $acc2 + adcx $acc6, $acc6 + .byte 0x67 + mulx %rdx, $t0, $t1 + mov 8*3+128($a_ptr), %rdx + adox $t4, $acc3 + adcx $acc7, $acc7 + adox $t0, $acc4 + mov \$32, $a_ptr + adox $t1, $acc5 + .byte 0x67,0x67 + mulx %rdx, $t0, $t4 + mov $acc0, %rdx + adox $t0, $acc6 + shlx $a_ptr, $acc0, $t0 + adox $t4, $acc7 + shrx $a_ptr, $acc0, $t4 + mov .Lpoly+8*3(%rip), $t1 + + # reduction step 1 + add $t0, $acc1 + adc $t4, $acc2 + + mulx $t1, $t0, $acc0 + mov $acc1, %rdx + adc $t0, $acc3 + shlx $a_ptr, $acc1, $t0 + adc \$0, $acc0 + shrx $a_ptr, $acc1, $t4 + + # reduction step 2 + add $t0, $acc2 + adc $t4, $acc3 + + mulx $t1, $t0, $acc1 + mov $acc2, %rdx + adc $t0, $acc0 + shlx $a_ptr, $acc2, $t0 + adc \$0, $acc1 + shrx $a_ptr, $acc2, $t4 + + # reduction step 3 + add $t0, $acc3 + adc $t4, $acc0 + + mulx $t1, $t0, $acc2 + mov $acc3, %rdx + adc $t0, $acc1 + shlx $a_ptr, $acc3, $t0 + adc \$0, $acc2 + shrx $a_ptr, $acc3, $t4 + + # reduction step 4 + add $t0, $acc0 + adc $t4, $acc1 + + mulx $t1, $t0, $acc3 + adc $t0, $acc2 + adc \$0, $acc3 + + xor $t3, $t3 # cf=0 + adc $acc0, $acc4 # accumulate upper half + mov .Lpoly+8*1(%rip), $a_ptr + adc $acc1, $acc5 + mov $acc4, $acc0 + adc $acc2, $acc6 + adc $acc3, $acc7 + mov $acc5, $acc1 + adc \$0, $t3 + + xor %eax, %eax # cf=0 + sbb \$-1, $acc4 # .Lpoly[0] + mov $acc6, $acc2 + sbb $a_ptr, $acc5 # .Lpoly[1] + sbb \$0, $acc6 # .Lpoly[2] + mov $acc7, $acc3 + sbb $t1, $acc7 # .Lpoly[3] + sbb \$0, $t3 + + cmovc $acc0, $acc4 + cmovc $acc1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $acc2, $acc6 + mov $acc5, 8*1($r_ptr) + cmovc $acc3, $acc7 + mov $acc6, 8*2($r_ptr) + mov $acc7, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sqr_montx,.-__ecp_nistz256_sqr_montx +___ +} +} +{ +my ($r_ptr,$in_ptr)=("%rdi","%rsi"); +my ($acc0,$acc1,$acc2,$acc3)=map("%r$_",(8..11)); +my ($t0,$t1,$t2)=("%rcx","%r12","%r13"); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_from_mont( +# uint64_t res[4], +# uint64_t in[4]); +# This one performs Montgomery multiplication by 1, so we only need the reduction + +.globl ecp_nistz256_from_mont +.type ecp_nistz256_from_mont,\@function,2 +.align 32 +ecp_nistz256_from_mont: + push %r12 + push %r13 + + mov 8*0($in_ptr), %rax + mov .Lpoly+8*3(%rip), $t2 + mov 8*1($in_ptr), $acc1 + mov 8*2($in_ptr), $acc2 + mov 8*3($in_ptr), $acc3 + mov %rax, $acc0 + mov .Lpoly+8*1(%rip), $t1 + + ######################################### + # First iteration + mov %rax, $t0 + shl \$32, $acc0 + mulq $t2 + shr \$32, $t0 + add $acc0, $acc1 + adc $t0, $acc2 + adc %rax, $acc3 + mov $acc1, %rax + adc \$0, %rdx + + ######################################### + # Second iteration + mov $acc1, $t0 + shl \$32, $acc1 + mov %rdx, $acc0 + mulq $t2 + shr \$32, $t0 + add $acc1, $acc2 + adc $t0, $acc3 + adc %rax, $acc0 + mov $acc2, %rax + adc \$0, %rdx + + ########################################## + # Third iteration + mov $acc2, $t0 + shl \$32, $acc2 + mov %rdx, $acc1 + mulq $t2 + shr \$32, $t0 + add $acc2, $acc3 + adc $t0, $acc0 + adc %rax, $acc1 + mov $acc3, %rax + adc \$0, %rdx + + ########################################### + # Last iteration + mov $acc3, $t0 + shl \$32, $acc3 + mov %rdx, $acc2 + mulq $t2 + shr \$32, $t0 + add $acc3, $acc0 + adc $t0, $acc1 + mov $acc0, $t0 + adc %rax, $acc2 + mov $acc1, $in_ptr + adc \$0, %rdx + + sub \$-1, $acc0 + mov $acc2, %rax + sbb $t1, $acc1 + sbb \$0, $acc2 + mov %rdx, $acc3 + sbb $t2, %rdx + sbb $t2, $t2 + + cmovnz $t0, $acc0 + cmovnz $in_ptr, $acc1 + mov $acc0, 8*0($r_ptr) + cmovnz %rax, $acc2 + mov $acc1, 8*1($r_ptr) + cmovz %rdx, $acc3 + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) + + pop %r13 + pop %r12 + ret +.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont +___ +} +{ +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($ONE,$INDEX,$Ra,$Rb,$Rc,$Rd,$Re,$Rf)=map("%xmm$_",(0..7)); +my ($M0,$T0a,$T0b,$T0c,$T0d,$T0e,$T0f,$TMP0)=map("%xmm$_",(8..15)); +my ($M1,$T2a,$T2b,$TMP2,$M2,$T2a,$T2b,$TMP2)=map("%xmm$_",(8..15)); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_select_w5(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_select_w5 +.type ecp_nistz256_select_w5,\@abi-omnipotent +.align 32 +ecp_nistz256_select_w5: +___ +$code.=<<___ if ($avx>1); + mov OPENSSL_ia32cap_P+8(%rip), %eax + test \$`1<<5`, %eax + jnz .Lavx2_select_w5 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_select_w5: + .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 .LOne(%rip), $ONE + movd $index, $INDEX + + pxor $Ra, $Ra + pxor $Rb, $Rb + pxor $Rc, $Rc + pxor $Rd, $Rd + pxor $Re, $Re + pxor $Rf, $Rf + + movdqa $ONE, $M0 + pshufd \$0, $INDEX, $INDEX + + mov \$16, %rax +.Lselect_loop_sse_w5: + + movdqa $M0, $TMP0 + paddd $ONE, $M0 + pcmpeqd $INDEX, $TMP0 + + movdqa 16*0($in_t), $T0a + movdqa 16*1($in_t), $T0b + movdqa 16*2($in_t), $T0c + movdqa 16*3($in_t), $T0d + movdqa 16*4($in_t), $T0e + movdqa 16*5($in_t), $T0f + lea 16*6($in_t), $in_t + + pand $TMP0, $T0a + pand $TMP0, $T0b + por $T0a, $Ra + pand $TMP0, $T0c + por $T0b, $Rb + pand $TMP0, $T0d + por $T0c, $Rc + pand $TMP0, $T0e + por $T0d, $Rd + pand $TMP0, $T0f + por $T0e, $Re + por $T0f, $Rf + + dec %rax + jnz .Lselect_loop_sse_w5 + + movdqu $Ra, 16*0($val) + movdqu $Rb, 16*1($val) + movdqu $Rc, 16*2($val) + movdqu $Rd, 16*3($val) + movdqu $Re, 16*4($val) + movdqu $Rf, 16*5($val) +___ +$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_ecp_nistz256_select_w5: +___ +$code.=<<___; + ret +.size ecp_nistz256_select_w5,.-ecp_nistz256_select_w5 + +################################################################################ +# void ecp_nistz256_select_w7(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_select_w7 +.type ecp_nistz256_select_w7,\@abi-omnipotent +.align 32 +ecp_nistz256_select_w7: +___ +$code.=<<___ if ($avx>1); + mov OPENSSL_ia32cap_P+8(%rip), %eax + test \$`1<<5`, %eax + jnz .Lavx2_select_w7 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_select_w7: + .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 .LOne(%rip), $M0 + movd $index, $INDEX + + pxor $Ra, $Ra + pxor $Rb, $Rb + pxor $Rc, $Rc + pxor $Rd, $Rd + + movdqa $M0, $ONE + pshufd \$0, $INDEX, $INDEX + mov \$64, %rax + +.Lselect_loop_sse_w7: + movdqa $M0, $TMP0 + paddd $ONE, $M0 + movdqa 16*0($in_t), $T0a + movdqa 16*1($in_t), $T0b + pcmpeqd $INDEX, $TMP0 + movdqa 16*2($in_t), $T0c + movdqa 16*3($in_t), $T0d + lea 16*4($in_t), $in_t + + pand $TMP0, $T0a + pand $TMP0, $T0b + por $T0a, $Ra + pand $TMP0, $T0c + por $T0b, $Rb + pand $TMP0, $T0d + por $T0c, $Rc + prefetcht0 255($in_t) + por $T0d, $Rd + + dec %rax + jnz .Lselect_loop_sse_w7 + + movdqu $Ra, 16*0($val) + movdqu $Rb, 16*1($val) + movdqu $Rc, 16*2($val) + movdqu $Rd, 16*3($val) +___ +$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_ecp_nistz256_select_w7: +___ +$code.=<<___; + ret +.size ecp_nistz256_select_w7,.-ecp_nistz256_select_w7 +___ +} +if ($avx>1) { +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($TWO,$INDEX,$Ra,$Rb,$Rc)=map("%ymm$_",(0..4)); +my ($M0,$T0a,$T0b,$T0c,$TMP0)=map("%ymm$_",(5..9)); +my ($M1,$T1a,$T1b,$T1c,$TMP1)=map("%ymm$_",(10..14)); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_avx2_select_w5(uint64_t *val, uint64_t *in_t, int index); +.type ecp_nistz256_avx2_select_w5,\@abi-omnipotent +.align 32 +ecp_nistz256_avx2_select_w5: +.Lavx2_select_w5: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_avx2_select_w5: + .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, 8(%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.=<<___; + vmovdqa .LTwo(%rip), $TWO + + vpxor $Ra, $Ra, $Ra + vpxor $Rb, $Rb, $Rb + vpxor $Rc, $Rc, $Rc + + vmovdqa .LOne(%rip), $M0 + vmovdqa .LTwo(%rip), $M1 + + vmovd $index, %xmm1 + vpermd $INDEX, $Ra, $INDEX + + mov \$8, %rax +.Lselect_loop_avx2_w5: + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + vmovdqa 32*2($in_t), $T0c + + vmovdqa 32*3($in_t), $T1a + vmovdqa 32*4($in_t), $T1b + vmovdqa 32*5($in_t), $T1c + + vpcmpeqd $INDEX, $M0, $TMP0 + vpcmpeqd $INDEX, $M1, $TMP1 + + vpaddd $TWO, $M0, $M0 + vpaddd $TWO, $M1, $M1 + lea 32*6($in_t), $in_t + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + vpand $TMP0, $T0c, $T0c + vpand $TMP1, $T1a, $T1a + vpand $TMP1, $T1b, $T1b + vpand $TMP1, $T1c, $T1c + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + vpxor $T0c, $Rc, $Rc + vpxor $T1a, $Ra, $Ra + vpxor $T1b, $Rb, $Rb + vpxor $T1c, $Rc, $Rc + + dec %rax + jnz .Lselect_loop_avx2_w5 + + vmovdqu $Ra, 32*0($val) + vmovdqu $Rb, 32*1($val) + vmovdqu $Rc, 32*2($val) + 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_ecp_nistz256_avx2_select_w5: +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_select_w5,.-ecp_nistz256_avx2_select_w5 +___ +} +if ($avx>1) { +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($THREE,$INDEX,$Ra,$Rb)=map("%ymm$_",(0..3)); +my ($M0,$T0a,$T0b,$TMP0)=map("%ymm$_",(4..7)); +my ($M1,$T1a,$T1b,$TMP1)=map("%ymm$_",(8..11)); +my ($M2,$T2a,$T2b,$TMP2)=map("%ymm$_",(12..15)); + +$code.=<<___; + +################################################################################ +# void ecp_nistz256_avx2_select_w7(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_avx2_select_w7 +.type ecp_nistz256_avx2_select_w7,\@abi-omnipotent +.align 32 +ecp_nistz256_avx2_select_w7: +.Lavx2_select_w7: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_avx2_select_w7: + .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, 8(%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.=<<___; + vmovdqa .LThree(%rip), $THREE + + vpxor $Ra, $Ra, $Ra + vpxor $Rb, $Rb, $Rb + + vmovdqa .LOne(%rip), $M0 + vmovdqa .LTwo(%rip), $M1 + vmovdqa .LThree(%rip), $M2 + + vmovd $index, %xmm1 + vpermd $INDEX, $Ra, $INDEX + # Skip index = 0, because it is implicitly the point at infinity + + mov \$21, %rax +.Lselect_loop_avx2_w7: + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + + vmovdqa 32*2($in_t), $T1a + vmovdqa 32*3($in_t), $T1b + + vmovdqa 32*4($in_t), $T2a + vmovdqa 32*5($in_t), $T2b + + vpcmpeqd $INDEX, $M0, $TMP0 + vpcmpeqd $INDEX, $M1, $TMP1 + vpcmpeqd $INDEX, $M2, $TMP2 + + vpaddd $THREE, $M0, $M0 + vpaddd $THREE, $M1, $M1 + vpaddd $THREE, $M2, $M2 + lea 32*6($in_t), $in_t + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + vpand $TMP1, $T1a, $T1a + vpand $TMP1, $T1b, $T1b + vpand $TMP2, $T2a, $T2a + vpand $TMP2, $T2b, $T2b + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + vpxor $T1a, $Ra, $Ra + vpxor $T1b, $Rb, $Rb + vpxor $T2a, $Ra, $Ra + vpxor $T2b, $Rb, $Rb + + dec %rax + jnz .Lselect_loop_avx2_w7 + + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + + vpcmpeqd $INDEX, $M0, $TMP0 + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + + vmovdqu $Ra, 32*0($val) + vmovdqu $Rb, 32*1($val) + 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_ecp_nistz256_avx2_select_w7: +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_select_w7,.-ecp_nistz256_avx2_select_w7 +___ +} else { +$code.=<<___; +.globl ecp_nistz256_avx2_select_w7 +.type ecp_nistz256_avx2_select_w7,\@function,3 +.align 32 +ecp_nistz256_avx2_select_w7: + .byte 0x0f,0x0b # ud2 + ret +.size ecp_nistz256_avx2_select_w7,.-ecp_nistz256_avx2_select_w7 +___ +} +{{{ +######################################################################## +# This block implements higher level point_double, point_add and +# point_add_affine. The key to performance in this case is to allow +# out-of-order execution logic to overlap computations from next step +# with tail processing from current step. By using tailored calling +# sequence we minimize inter-step overhead to give processor better +# shot at overlapping operations... +# +# You will notice that input data is copied to stack. Trouble is that +# there are no registers to spare for holding original pointers and +# reloading them, pointers, would create undesired dependencies on +# effective addresses calculation paths. In other words it's too done +# to favour out-of-order execution logic. +# + +my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx"); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15)); +my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rbp","%rcx",$acc4,$acc4); +my ($poly1,$poly3)=($acc6,$acc7); + +sub load_for_mul () { +my ($a,$b,$src0) = @_; +my $bias = $src0 eq "%rax" ? 0 : -128; + +" mov $b, $src0 + lea $b, $b_ptr + mov 8*0+$a, $acc1 + mov 8*1+$a, $acc2 + lea $bias+$a, $a_ptr + mov 8*2+$a, $acc3 + mov 8*3+$a, $acc4" +} + +sub load_for_sqr () { +my ($a,$src0) = @_; +my $bias = $src0 eq "%rax" ? 0 : -128; + +" mov 8*0+$a, $src0 + mov 8*1+$a, $acc6 + lea $bias+$a, $a_ptr + mov 8*2+$a, $acc7 + mov 8*3+$a, $acc0" +} + + { +######################################################################## +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); + +$code.=<<___; +.type __ecp_nistz256_add_toq,\@abi-omnipotent +.align 32 +__ecp_nistz256_add_toq: + add 8*0($b_ptr), $a0 + adc 8*1($b_ptr), $a1 + mov $a0, $t0 + adc 8*2($b_ptr), $a2 + adc 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb $t4, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_add_toq,.-__ecp_nistz256_add_toq + +.type __ecp_nistz256_sub_fromq,\@abi-omnipotent +.align 32 +__ecp_nistz256_sub_fromq: + sub 8*0($b_ptr), $a0 + sbb 8*1($b_ptr), $a1 + mov $a0, $t0 + sbb 8*2($b_ptr), $a2 + sbb 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb $t4, $t4 + + add \$-1, $a0 + mov $a2, $t2 + adc $poly1, $a1 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sub_fromq,.-__ecp_nistz256_sub_fromq + +.type __ecp_nistz256_subq,\@abi-omnipotent +.align 32 +__ecp_nistz256_subq: + sub $a0, $t0 + sbb $a1, $t1 + mov $t0, $a0 + sbb $a2, $t2 + sbb $a3, $t3 + mov $t1, $a1 + sbb $t4, $t4 + + add \$-1, $t0 + mov $t2, $a2 + adc $poly1, $t1 + adc \$0, $t2 + mov $t3, $a3 + adc $poly3, $t3 + test $t4, $t4 + + cmovnz $t0, $a0 + cmovnz $t1, $a1 + cmovnz $t2, $a2 + cmovnz $t3, $a3 + + ret +.size __ecp_nistz256_subq,.-__ecp_nistz256_subq + +.type __ecp_nistz256_mul_by_2q,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_by_2q: + add $a0, $a0 # a0:a3+a0:a3 + adc $a1, $a1 + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + sbb $t4, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_by_2q,.-__ecp_nistz256_mul_by_2q +___ + } +sub gen_double () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($S,$M,$Zsqr,$in_x,$tmp0)=map(32*$_,(0..4)); + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_double +.type ecp_nistz256_point_double,\@function,2 +.align 32 +ecp_nistz256_point_double: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_doublex +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_doublex,\@function,2 +.align 32 +ecp_nistz256_point_doublex: +.Lpoint_doublex: +___ + } +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + sub \$32*5+8, %rsp + +.Lpoint_double_shortcut$x: + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr.x + mov $a_ptr, $b_ptr # backup copy + movdqu 0x10($a_ptr), %xmm1 + mov 0x20+8*0($a_ptr), $acc4 # load in_y in "5-4-0-1" order + mov 0x20+8*1($a_ptr), $acc5 + mov 0x20+8*2($a_ptr), $acc0 + mov 0x20+8*3($a_ptr), $acc1 + mov .Lpoly+8*1(%rip), $poly1 + mov .Lpoly+8*3(%rip), $poly3 + movdqa %xmm0, $in_x(%rsp) + movdqa %xmm1, $in_x+0x10(%rsp) + lea 0x20($r_ptr), $acc2 + lea 0x40($r_ptr), $acc3 + movq $r_ptr, %xmm0 + movq $acc2, %xmm1 + movq $acc3, %xmm2 + + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(S, in_y); + + mov 0x40+8*0($a_ptr), $src0 + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + lea 0x40-$bias($a_ptr), $a_ptr + lea $Zsqr(%rsp), $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Zsqr, in_z); + + `&load_for_sqr("$S(%rsp)", "$src0")` + lea $S(%rsp), $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(S, S); + + mov 0x20($b_ptr), $src0 # $b_ptr is still valid + mov 0x40+8*0($b_ptr), $acc1 + mov 0x40+8*1($b_ptr), $acc2 + mov 0x40+8*2($b_ptr), $acc3 + mov 0x40+8*3($b_ptr), $acc4 + lea 0x40-$bias($b_ptr), $a_ptr + lea 0x20($b_ptr), $b_ptr + movq %xmm2, $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, in_z, in_y); + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(res_z, res_z); + + mov $in_x+8*0(%rsp), $acc4 # "5-4-0-1" order + mov $in_x+8*1(%rsp), $acc5 + lea $Zsqr(%rsp), $b_ptr + mov $in_x+8*2(%rsp), $acc0 + mov $in_x+8*3(%rsp), $acc1 + lea $M(%rsp), $r_ptr + call __ecp_nistz256_add_to$x # p256_add(M, in_x, Zsqr); + + mov $in_x+8*0(%rsp), $acc4 # "5-4-0-1" order + mov $in_x+8*1(%rsp), $acc5 + lea $Zsqr(%rsp), $b_ptr + mov $in_x+8*2(%rsp), $acc0 + mov $in_x+8*3(%rsp), $acc1 + lea $Zsqr(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(Zsqr, in_x, Zsqr); + + `&load_for_sqr("$S(%rsp)", "$src0")` + movq %xmm1, $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_y, S); +___ +{ +######## ecp_nistz256_div_by_2(res_y, res_y); ########################## +# operate in 4-5-6-7 "name space" that matches squaring output +# +my ($poly1,$poly3)=($a_ptr,$t1); +my ($a0,$a1,$a2,$a3,$t3,$t4,$t1)=($acc4,$acc5,$acc6,$acc7,$acc0,$acc1,$acc2); + +$code.=<<___; + xor $t4, $t4 + mov $a0, $t0 + add \$-1, $a0 + mov $a1, $t1 + adc $poly1, $a1 + mov $a2, $t2 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + adc \$0, $t4 + xor $a_ptr, $a_ptr # borrow $a_ptr + test \$1, $t0 + + cmovz $t0, $a0 + cmovz $t1, $a1 + cmovz $t2, $a2 + cmovz $t3, $a3 + cmovz $a_ptr, $t4 + + mov $a1, $t0 # a0:a3>>1 + shr \$1, $a0 + shl \$63, $t0 + mov $a2, $t1 + shr \$1, $a1 + or $t0, $a0 + shl \$63, $t1 + mov $a3, $t2 + shr \$1, $a2 + or $t1, $a1 + shl \$63, $t2 + mov $a0, 8*0($r_ptr) + shr \$1, $a3 + mov $a1, 8*1($r_ptr) + shl \$63, $t4 + or $t2, $a2 + or $t4, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$M(%rsp)", "$Zsqr(%rsp)", "$src0")` + lea $M(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(M, M, Zsqr); + + lea $tmp0(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x + + lea $M(%rsp), $b_ptr + lea $M(%rsp), $r_ptr + call __ecp_nistz256_add_to$x # p256_mul_by_3(M, M); + + `&load_for_mul("$S(%rsp)", "$in_x(%rsp)", "$src0")` + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S, S, in_x); + + lea $tmp0(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(tmp0, S); + + `&load_for_sqr("$M(%rsp)", "$src0")` + movq %xmm0, $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_x, M); + + lea $tmp0(%rsp), $b_ptr + mov $acc6, $acc0 # harmonize sqr output and sub input + mov $acc7, $acc1 + mov $a_ptr, $poly1 + mov $t1, $poly3 + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, tmp0); + + mov $S+8*0(%rsp), $t0 + mov $S+8*1(%rsp), $t1 + mov $S+8*2(%rsp), $t2 + mov $S+8*3(%rsp), $acc2 # "4-5-0-1" order + lea $S(%rsp), $r_ptr + call __ecp_nistz256_sub$x # p256_sub(S, S, res_x); + + mov $M(%rsp), $src0 + lea $M(%rsp), $b_ptr + mov $acc4, $acc6 # harmonize sub output and mul input + xor %ecx, %ecx + mov $acc4, $S+8*0(%rsp) # have to save:-( + mov $acc5, $acc2 + mov $acc5, $S+8*1(%rsp) + cmovz $acc0, $acc3 + mov $acc0, $S+8*2(%rsp) + lea $S-$bias(%rsp), $a_ptr + cmovz $acc1, $acc4 + mov $acc1, $S+8*3(%rsp) + mov $acc6, $acc1 + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S, S, M); + + movq %xmm1, $b_ptr + movq %xmm1, $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, S, res_y); + + add \$32*5+8, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_point_double$sfx,.-ecp_nistz256_point_double$sfx +___ +} +&gen_double("q"); + +sub gen_add () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2, + $res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y,$in2_z)=map(32*$_,(0..17)); + my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_add +.type ecp_nistz256_point_add,\@function,3 +.align 32 +ecp_nistz256_point_add: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_addx +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_addx,\@function,3 +.align 32 +ecp_nistz256_point_addx: +.Lpoint_addx: +___ + } +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + sub \$32*18+8, %rsp + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + movdqu 0x30($a_ptr), %xmm3 + movdqu 0x40($a_ptr), %xmm4 + movdqu 0x50($a_ptr), %xmm5 + mov $a_ptr, $b_ptr # reassign + mov $b_org, $a_ptr # reassign + movdqa %xmm0, $in1_x(%rsp) + movdqa %xmm1, $in1_x+0x10(%rsp) + por %xmm0, %xmm1 + movdqa %xmm2, $in1_y(%rsp) + movdqa %xmm3, $in1_y+0x10(%rsp) + por %xmm2, %xmm3 + movdqa %xmm4, $in1_z(%rsp) + movdqa %xmm5, $in1_z+0x10(%rsp) + por %xmm1, %xmm3 + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$b_ptr + pshufd \$0xb1, %xmm3, %xmm5 + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + por %xmm3, %xmm5 + movdqu 0x30($a_ptr), %xmm3 + mov 0x40+8*0($a_ptr), $src0 # load original in2_z + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + movdqa %xmm0, $in2_x(%rsp) + pshufd \$0x1e, %xmm5, %xmm4 + movdqa %xmm1, $in2_x+0x10(%rsp) + por %xmm0, %xmm1 + movq $r_ptr, %xmm0 # save $r_ptr + movdqa %xmm2, $in2_y(%rsp) + movdqa %xmm3, $in2_y+0x10(%rsp) + por %xmm2, %xmm3 + por %xmm4, %xmm5 + pxor %xmm4, %xmm4 + por %xmm1, %xmm3 + + lea 0x40-$bias($a_ptr), $a_ptr # $a_ptr is still valid + mov $src0, $in2_z+8*0(%rsp) # make in2_z copy + mov $acc6, $in2_z+8*1(%rsp) + mov $acc7, $in2_z+8*2(%rsp) + mov $acc0, $in2_z+8*3(%rsp) + lea $Z2sqr(%rsp), $r_ptr # Z2^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z2sqr, in2_z); + + pcmpeqd %xmm4, %xmm5 + pshufd \$0xb1, %xmm3, %xmm4 + por %xmm3, %xmm4 + pshufd \$0, %xmm5, %xmm5 # in1infty + pshufd \$0x1e, %xmm4, %xmm3 + por %xmm3, %xmm4 + pxor %xmm3, %xmm3 + pcmpeqd %xmm3, %xmm4 + pshufd \$0, %xmm4, %xmm4 # in2infty + mov 0x40+8*0($b_ptr), $src0 # load original in1_z + mov 0x40+8*1($b_ptr), $acc6 + mov 0x40+8*2($b_ptr), $acc7 + mov 0x40+8*3($b_ptr), $acc0 + movq $b_ptr, %xmm1 + + lea 0x40-$bias($b_ptr), $a_ptr + lea $Z1sqr(%rsp), $r_ptr # Z1^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z1sqr, in1_z); + + `&load_for_mul("$Z2sqr(%rsp)", "$in2_z(%rsp)", "$src0")` + lea $S1(%rsp), $r_ptr # S1 = Z2^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S1, Z2sqr, in2_z); + + `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Z1sqr, in1_z); + + `&load_for_mul("$S1(%rsp)", "$in1_y(%rsp)", "$src0")` + lea $S1(%rsp), $r_ptr # S1 = Y1*Z2^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S1, S1, in1_y); + + `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Y2*Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S2, in2_y); + + lea $S1(%rsp), $b_ptr + lea $R(%rsp), $r_ptr # R = S2 - S1 + call __ecp_nistz256_sub_from$x # p256_sub(R, S2, S1); + + or $acc5, $acc4 # see if result is zero + movdqa %xmm4, %xmm2 + or $acc0, $acc4 + or $acc1, $acc4 + por %xmm5, %xmm2 # in1infty || in2infty + movq $acc4, %xmm3 + + `&load_for_mul("$Z2sqr(%rsp)", "$in1_x(%rsp)", "$src0")` + lea $U1(%rsp), $r_ptr # U1 = X1*Z2^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U1, in1_x, Z2sqr); + + `&load_for_mul("$Z1sqr(%rsp)", "$in2_x(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U2 = X2*Z1^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, in2_x, Z1sqr); + + lea $U1(%rsp), $b_ptr + lea $H(%rsp), $r_ptr # H = U2 - U1 + call __ecp_nistz256_sub_from$x # p256_sub(H, U2, U1); + + or $acc5, $acc4 # see if result is zero + or $acc0, $acc4 + or $acc1, $acc4 + + .byte 0x3e # predict taken + jnz .Ladd_proceed$x # is_equal(U1,U2)? + movq %xmm2, $acc0 + movq %xmm3, $acc1 + test $acc0, $acc0 + jnz .Ladd_proceed$x # (in1infty || in2infty)? + test $acc1, $acc1 + jz .Ladd_double$x # is_equal(S1,S2)? + + movq %xmm0, $r_ptr # restore $r_ptr + pxor %xmm0, %xmm0 + movdqu %xmm0, 0x00($r_ptr) + movdqu %xmm0, 0x10($r_ptr) + movdqu %xmm0, 0x20($r_ptr) + movdqu %xmm0, 0x30($r_ptr) + movdqu %xmm0, 0x40($r_ptr) + movdqu %xmm0, 0x50($r_ptr) + jmp .Ladd_done$x + +.align 32 +.Ladd_double$x: + movq %xmm1, $a_ptr # restore $a_ptr + movq %xmm0, $r_ptr # restore $r_ptr + add \$`32*(18-5)`, %rsp # difference in frame sizes + jmp .Lpoint_double_shortcut$x + +.align 32 +.Ladd_proceed$x: + `&load_for_sqr("$R(%rsp)", "$src0")` + lea $Rsqr(%rsp), $r_ptr # R^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Rsqr, R); + + `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, H, in1_z); + + `&load_for_sqr("$H(%rsp)", "$src0")` + lea $Hsqr(%rsp), $r_ptr # H^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Hsqr, H); + + `&load_for_mul("$res_z(%rsp)", "$in2_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, res_z, in2_z); + + `&load_for_mul("$Hsqr(%rsp)", "$H(%rsp)", "$src0")` + lea $Hcub(%rsp), $r_ptr # H^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(Hcub, Hsqr, H); + + `&load_for_mul("$Hsqr(%rsp)", "$U1(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U1*H^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, U1, Hsqr); +___ +{ +####################################################################### +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); +my ($poly1, $poly3)=($acc6,$acc7); + +$code.=<<___; + #lea $U2(%rsp), $a_ptr + #lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2 + #call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2); + + add $acc0, $acc0 # a0:a3+a0:a3 + lea $Rsqr(%rsp), $a_ptr + adc $acc1, $acc1 + mov $acc0, $t0 + adc $acc2, $acc2 + adc $acc3, $acc3 + mov $acc1, $t1 + sbb $t4, $t4 + + sub \$-1, $acc0 + mov $acc2, $t2 + sbb $poly1, $acc1 + sbb \$0, $acc2 + mov $acc3, $t3 + sbb $poly3, $acc3 + test $t4, $t4 + + cmovz $t0, $acc0 + mov 8*0($a_ptr), $t0 + cmovz $t1, $acc1 + mov 8*1($a_ptr), $t1 + cmovz $t2, $acc2 + mov 8*2($a_ptr), $t2 + cmovz $t3, $acc3 + mov 8*3($a_ptr), $t3 + + call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr); + + lea $Hcub(%rsp), $b_ptr + lea $res_x(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, Hcub); + + mov $U2+8*0(%rsp), $t0 + mov $U2+8*1(%rsp), $t1 + mov $U2+8*2(%rsp), $t2 + mov $U2+8*3(%rsp), $t3 + lea $res_y(%rsp), $r_ptr + + call __ecp_nistz256_sub$x # p256_sub(res_y, U2, res_x); + + mov $acc0, 8*0($r_ptr) # save the result, as + mov $acc1, 8*1($r_ptr) # __ecp_nistz256_sub doesn't + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$S1(%rsp)", "$Hcub(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S1, Hcub); + + `&load_for_mul("$R(%rsp)", "$res_y(%rsp)", "$src0")` + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_y, R, res_y); + + lea $S2(%rsp), $b_ptr + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, res_y, S2); + + movq %xmm0, $r_ptr # restore $r_ptr + + movdqa %xmm5, %xmm0 # copy_conditional(res_z, in2_z, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_z(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_z+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_z(%rsp), %xmm2 + pand $in2_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_z, in1_z, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_z(%rsp), %xmm2 + pand $in1_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x40($r_ptr) + movdqu %xmm3, 0x50($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_x, in2_x, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_x(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_x+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_x(%rsp), %xmm2 + pand $in2_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_x, in1_x, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_x(%rsp), %xmm2 + pand $in1_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x00($r_ptr) + movdqu %xmm3, 0x10($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_y, in2_y, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_y(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_y+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_y(%rsp), %xmm2 + pand $in2_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_y, in1_y, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_y(%rsp), %xmm2 + pand $in1_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x20($r_ptr) + movdqu %xmm3, 0x30($r_ptr) + +.Ladd_done$x: + add \$32*18+8, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_point_add$sfx,.-ecp_nistz256_point_add$sfx +___ +} +&gen_add("q"); + +sub gen_add_affine () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr, + $res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y)=map(32*$_,(0..14)); + my $Z1sqr = $S2; + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_add_affine +.type ecp_nistz256_point_add_affine,\@function,3 +.align 32 +ecp_nistz256_point_add_affine: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_add_affinex +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_add_affinex,\@function,3 +.align 32 +ecp_nistz256_point_add_affinex: +.Lpoint_add_affinex: +___ + } +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + sub \$32*15+8, %rsp + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr + mov $b_org, $b_ptr # reassign + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + movdqu 0x30($a_ptr), %xmm3 + movdqu 0x40($a_ptr), %xmm4 + movdqu 0x50($a_ptr), %xmm5 + mov 0x40+8*0($a_ptr), $src0 # load original in1_z + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + movdqa %xmm0, $in1_x(%rsp) + movdqa %xmm1, $in1_x+0x10(%rsp) + por %xmm0, %xmm1 + movdqa %xmm2, $in1_y(%rsp) + movdqa %xmm3, $in1_y+0x10(%rsp) + por %xmm2, %xmm3 + movdqa %xmm4, $in1_z(%rsp) + movdqa %xmm5, $in1_z+0x10(%rsp) + por %xmm1, %xmm3 + + movdqu 0x00($b_ptr), %xmm0 # copy *(P256_POINT_AFFINE *)$b_ptr + pshufd \$0xb1, %xmm3, %xmm5 + movdqu 0x10($b_ptr), %xmm1 + movdqu 0x20($b_ptr), %xmm2 + por %xmm3, %xmm5 + movdqu 0x30($b_ptr), %xmm3 + movdqa %xmm0, $in2_x(%rsp) + pshufd \$0x1e, %xmm5, %xmm4 + movdqa %xmm1, $in2_x+0x10(%rsp) + por %xmm0, %xmm1 + movq $r_ptr, %xmm0 # save $r_ptr + movdqa %xmm2, $in2_y(%rsp) + movdqa %xmm3, $in2_y+0x10(%rsp) + por %xmm2, %xmm3 + por %xmm4, %xmm5 + pxor %xmm4, %xmm4 + por %xmm1, %xmm3 + + lea 0x40-$bias($a_ptr), $a_ptr # $a_ptr is still valid + lea $Z1sqr(%rsp), $r_ptr # Z1^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z1sqr, in1_z); + + pcmpeqd %xmm4, %xmm5 + pshufd \$0xb1, %xmm3, %xmm4 + mov 0x00($b_ptr), $src0 # $b_ptr is still valid + #lea 0x00($b_ptr), $b_ptr + mov $acc4, $acc1 # harmonize sqr output and mul input + por %xmm3, %xmm4 + pshufd \$0, %xmm5, %xmm5 # in1infty + pshufd \$0x1e, %xmm4, %xmm3 + mov $acc5, $acc2 + por %xmm3, %xmm4 + pxor %xmm3, %xmm3 + mov $acc6, $acc3 + pcmpeqd %xmm3, %xmm4 + pshufd \$0, %xmm4, %xmm4 # in2infty + + lea $Z1sqr-$bias(%rsp), $a_ptr + mov $acc7, $acc4 + lea $U2(%rsp), $r_ptr # U2 = X2*Z1^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, Z1sqr, in2_x); + + lea $in1_x(%rsp), $b_ptr + lea $H(%rsp), $r_ptr # H = U2 - U1 + call __ecp_nistz256_sub_from$x # p256_sub(H, U2, in1_x); + + `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Z1sqr, in1_z); + + `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, H, in1_z); + + `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Y2*Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S2, in2_y); + + lea $in1_y(%rsp), $b_ptr + lea $R(%rsp), $r_ptr # R = S2 - S1 + call __ecp_nistz256_sub_from$x # p256_sub(R, S2, in1_y); + + `&load_for_sqr("$H(%rsp)", "$src0")` + lea $Hsqr(%rsp), $r_ptr # H^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Hsqr, H); + + `&load_for_sqr("$R(%rsp)", "$src0")` + lea $Rsqr(%rsp), $r_ptr # R^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Rsqr, R); + + `&load_for_mul("$H(%rsp)", "$Hsqr(%rsp)", "$src0")` + lea $Hcub(%rsp), $r_ptr # H^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(Hcub, Hsqr, H); + + `&load_for_mul("$Hsqr(%rsp)", "$in1_x(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U1*H^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, in1_x, Hsqr); +___ +{ +####################################################################### +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); +my ($poly1, $poly3)=($acc6,$acc7); + +$code.=<<___; + #lea $U2(%rsp), $a_ptr + #lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2 + #call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2); + + add $acc0, $acc0 # a0:a3+a0:a3 + lea $Rsqr(%rsp), $a_ptr + adc $acc1, $acc1 + mov $acc0, $t0 + adc $acc2, $acc2 + adc $acc3, $acc3 + mov $acc1, $t1 + sbb $t4, $t4 + + sub \$-1, $acc0 + mov $acc2, $t2 + sbb $poly1, $acc1 + sbb \$0, $acc2 + mov $acc3, $t3 + sbb $poly3, $acc3 + test $t4, $t4 + + cmovz $t0, $acc0 + mov 8*0($a_ptr), $t0 + cmovz $t1, $acc1 + mov 8*1($a_ptr), $t1 + cmovz $t2, $acc2 + mov 8*2($a_ptr), $t2 + cmovz $t3, $acc3 + mov 8*3($a_ptr), $t3 + + call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr); + + lea $Hcub(%rsp), $b_ptr + lea $res_x(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, Hcub); + + mov $U2+8*0(%rsp), $t0 + mov $U2+8*1(%rsp), $t1 + mov $U2+8*2(%rsp), $t2 + mov $U2+8*3(%rsp), $t3 + lea $H(%rsp), $r_ptr + + call __ecp_nistz256_sub$x # p256_sub(H, U2, res_x); + + mov $acc0, 8*0($r_ptr) # save the result, as + mov $acc1, 8*1($r_ptr) # __ecp_nistz256_sub doesn't + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$Hcub(%rsp)", "$in1_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Hcub, in1_y); + + `&load_for_mul("$H(%rsp)", "$R(%rsp)", "$src0")` + lea $H(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(H, H, R); + + lea $S2(%rsp), $b_ptr + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, H, S2); + + movq %xmm0, $r_ptr # restore $r_ptr + + movdqa %xmm5, %xmm0 # copy_conditional(res_z, ONE, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_z(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_z+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand .LONE_mont(%rip), %xmm2 + pand .LONE_mont+0x10(%rip), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_z, in1_z, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_z(%rsp), %xmm2 + pand $in1_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x40($r_ptr) + movdqu %xmm3, 0x50($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_x, in2_x, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_x(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_x+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_x(%rsp), %xmm2 + pand $in2_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_x, in1_x, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_x(%rsp), %xmm2 + pand $in1_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x00($r_ptr) + movdqu %xmm3, 0x10($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_y, in2_y, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_y(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_y+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_y(%rsp), %xmm2 + pand $in2_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_y, in1_y, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_y(%rsp), %xmm2 + pand $in1_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x20($r_ptr) + movdqu %xmm3, 0x30($r_ptr) + + add \$32*15+8, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_point_add_affine$sfx,.-ecp_nistz256_point_add_affine$sfx +___ +} +&gen_add_affine("q"); + +######################################################################## +# AD*X magic +# +if ($addx) { { +######################################################################## +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); + +$code.=<<___; +.type __ecp_nistz256_add_tox,\@abi-omnipotent +.align 32 +__ecp_nistz256_add_tox: + xor $t4, $t4 + adc 8*0($b_ptr), $a0 + adc 8*1($b_ptr), $a1 + mov $a0, $t0 + adc 8*2($b_ptr), $a2 + adc 8*3($b_ptr), $a3 + mov $a1, $t1 + adc \$0, $t4 + + xor $t3, $t3 + sbb \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + + bt \$0, $t4 + cmovnc $t0, $a0 + cmovnc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovnc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovnc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_add_tox,.-__ecp_nistz256_add_tox + +.type __ecp_nistz256_sub_fromx,\@abi-omnipotent +.align 32 +__ecp_nistz256_sub_fromx: + xor $t4, $t4 + sbb 8*0($b_ptr), $a0 + sbb 8*1($b_ptr), $a1 + mov $a0, $t0 + sbb 8*2($b_ptr), $a2 + sbb 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb \$0, $t4 + + xor $t3, $t3 + adc \$-1, $a0 + mov $a2, $t2 + adc $poly1, $a1 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + + bt \$0, $t4 + cmovnc $t0, $a0 + cmovnc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovnc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovnc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sub_fromx,.-__ecp_nistz256_sub_fromx + +.type __ecp_nistz256_subx,\@abi-omnipotent +.align 32 +__ecp_nistz256_subx: + xor $t4, $t4 + sbb $a0, $t0 + sbb $a1, $t1 + mov $t0, $a0 + sbb $a2, $t2 + sbb $a3, $t3 + mov $t1, $a1 + sbb \$0, $t4 + + xor $a3 ,$a3 + adc \$-1, $t0 + mov $t2, $a2 + adc $poly1, $t1 + adc \$0, $t2 + mov $t3, $a3 + adc $poly3, $t3 + + bt \$0, $t4 + cmovc $t0, $a0 + cmovc $t1, $a1 + cmovc $t2, $a2 + cmovc $t3, $a3 + + ret +.size __ecp_nistz256_subx,.-__ecp_nistz256_subx + +.type __ecp_nistz256_mul_by_2x,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_by_2x: + xor $t4, $t4 + adc $a0, $a0 # a0:a3+a0:a3 + adc $a1, $a1 + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + adc \$0, $t4 + + xor $t3, $t3 + sbb \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + + bt \$0, $t4 + cmovnc $t0, $a0 + cmovnc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovnc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovnc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_by_2x,.-__ecp_nistz256_mul_by_2x +___ + } +&gen_double("x"); +&gen_add("x"); +&gen_add_affine("x"); +} +}}} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/ec/ec.c b/external/boringssl/crypto/ec/ec.c new file mode 100644 index 0000000000..8f3fa6e13a --- /dev/null +++ b/external/boringssl/crypto/ec/ec.c @@ -0,0 +1,935 @@ +/* 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 + +#include +#include + +#include +#include +#include +#include + +#include "internal.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}}; + +/* MSan appears to have a bug that causes code to be miscompiled in opt mode. + * While that is being looked at, don't run the uint128_t code under MSan. */ +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) && \ + !defined(MEMORY_SANITIZER) +#define BORINGSSL_USE_INT128_CODE +#endif + +const struct built_in_curve OPENSSL_built_in_curves[] = { + { + NID_secp521r1, + /* 1.3.132.0.35 */ + {0x2b, 0x81, 0x04, 0x00, 0x23}, 5, + &P521, + NULL, + }, + { + NID_secp384r1, + /* 1.3.132.0.34 */ + {0x2b, 0x81, 0x04, 0x00, 0x22}, 5, + &P384, + NULL, + }, + { + NID_X9_62_prime256v1, + /* 1.2.840.10045.3.1.7 */ + {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, 8, + &P256, +#if defined(BORINGSSL_USE_INT128_CODE) +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ + !defined(OPENSSL_SMALL) + EC_GFp_nistz256_method, +#else + EC_GFp_nistp256_method, +#endif +#else + NULL, +#endif + }, + { + NID_secp224r1, + /* 1.3.132.0.33 */ + {0x2b, 0x81, 0x04, 0x00, 0x21}, 5, + &P224, +#if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL) + EC_GFp_nistp224_method, +#else + NULL, +#endif + }, + {NID_undef, {0}, 0, NULL, NULL}, +}; + +/* built_in_curve_scalar_field_monts contains Montgomery contexts for + * performing inversions in the scalar fields of each of the built-in + * curves. It's protected by |built_in_curve_scalar_field_monts_once|. */ +static const BN_MONT_CTX **built_in_curve_scalar_field_monts; + +static CRYPTO_once_t built_in_curve_scalar_field_monts_once; + +static void built_in_curve_scalar_field_monts_init(void) { + unsigned num_built_in_curves; + for (num_built_in_curves = 0;; num_built_in_curves++) { + if (OPENSSL_built_in_curves[num_built_in_curves].nid == NID_undef) { + break; + } + } + + assert(0 < num_built_in_curves); + + built_in_curve_scalar_field_monts = + OPENSSL_malloc(sizeof(BN_MONT_CTX *) * num_built_in_curves); + if (built_in_curve_scalar_field_monts == NULL) { + return; + } + + BIGNUM *order = BN_new(); + BN_CTX *bn_ctx = BN_CTX_new(); + BN_MONT_CTX *mont_ctx = NULL; + + if (bn_ctx == NULL || + order == NULL) { + goto err; + } + + unsigned i; + for (i = 0; i < num_built_in_curves; i++) { + const struct curve_data *curve = OPENSSL_built_in_curves[i].data; + const unsigned param_len = curve->param_len; + const uint8_t *params = curve->data; + + mont_ctx = BN_MONT_CTX_new(); + if (mont_ctx == NULL) { + goto err; + } + + if (!BN_bin2bn(params + 5 * param_len, param_len, order) || + !BN_MONT_CTX_set(mont_ctx, order, bn_ctx)) { + goto err; + } + + built_in_curve_scalar_field_monts[i] = mont_ctx; + mont_ctx = NULL; + } + + goto out; + +err: + BN_MONT_CTX_free(mont_ctx); + OPENSSL_free((BN_MONT_CTX**) built_in_curve_scalar_field_monts); + built_in_curve_scalar_field_monts = NULL; + +out: + BN_free(order); + BN_CTX_free(bn_ctx); +} + +EC_GROUP *ec_group_new(const EC_METHOD *meth) { + EC_GROUP *ret; + + if (meth == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_SLOT_FULL); + return NULL; + } + + if (meth->group_init == 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } + + ret = OPENSSL_malloc(sizeof(EC_GROUP)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, 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; +} + +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, 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; +} + +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor) { + if (group->curve_name != NID_undef || group->generator != NULL) { + /* |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by + * |EC_GROUP_new_curve_GFp| and may only used once on each group. */ + return 0; + } + + group->generator = EC_POINT_new(group); + return group->generator != NULL && + EC_POINT_copy(group->generator, generator) && + BN_copy(&group->order, order) && + BN_copy(&group->cofactor, cofactor); +} + +EC_GROUP *EC_GROUP_new_arbitrary(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, const BIGNUM *gx, + const BIGNUM *gy, const BIGNUM *order, + const BIGNUM *cofactor) { + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return NULL; + } + + EC_POINT *generator = NULL; + EC_GROUP *ret = EC_GROUP_new_curve_GFp(p, a, b, ctx); + if (ret == NULL) { + goto err; + } + + generator = EC_POINT_new(ret); + if (generator == NULL || + !EC_POINT_set_affine_coordinates_GFp(ret, generator, gx, gy, ctx) || + !EC_GROUP_set_generator(ret, generator, order, cofactor)) { + goto err; + } + + EC_POINT_free(generator); + BN_CTX_free(ctx); + return ret; + +err: + EC_POINT_free(generator); + EC_GROUP_free(ret); + BN_CTX_free(ctx); + return NULL; +} + +static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[built_in_index]; + EC_GROUP *group = NULL; + EC_POINT *P = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; + const EC_METHOD *meth; + int ok = 0; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + const struct curve_data *data = curve->data; + const unsigned param_len = data->param_len; + const uint8_t *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, 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, ERR_R_EC_LIB); + goto err; + } + } else { + if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + } + + if ((P = EC_POINT_new(group)) == NULL) { + OPENSSL_PUT_ERROR(EC, 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, ERR_R_BN_LIB); + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order) || + !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + + CRYPTO_once(&built_in_curve_scalar_field_monts_once, + built_in_curve_scalar_field_monts_init); + if (built_in_curve_scalar_field_monts != NULL) { + group->mont_data = built_in_curve_scalar_field_monts[built_in_index]; + } + + group->generator = P; + P = NULL; + ok = 1; + +err: + if (!ok) { + EC_GROUP_free(group); + group = NULL; + } + EC_POINT_free(P); + BN_CTX_free(ctx); + BN_free(p); + BN_free(a); + BN_free(b); + BN_free(x); + 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(i); + break; + } + } + + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, 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_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, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (dest->meth != src->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) { + return 1; + } + + dest->mont_data = src->mont_data; + + 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 { + 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); +} + +const BN_MONT_CTX *ec_group_get_mont_data(const EC_GROUP *group) { + return group->mont_data; +} + +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) { + EC_GROUP_free(t); + return NULL; + } else { + return t; + } +} + +int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) { + return a->curve_name == NID_undef || + b->curve_name == NID_undef || + a->curve_name != b->curve_name; +} + +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) { + return group->generator; +} + +const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) { + assert(!BN_is_zero(&group->order)); + return &group->order; +} + +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) { + if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) { + return 0; + } + return 1; +} + +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) { + return ec_GFp_simple_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; } + +unsigned EC_GROUP_get_degree(const EC_GROUP *group) { + return ec_GFp_simple_group_get_degree(group); +} + +EC_POINT *EC_POINT_new(const EC_GROUP *group) { + EC_POINT *ret; + + if (group == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->meth = group->meth; + + if (!ec_GFp_simple_point_init(ret)) { + OPENSSL_free(ret); + return NULL; + } + + return ret; +} + +void EC_POINT_free(EC_POINT *point) { + if (!point) { + return; + } + + ec_GFp_simple_point_finish(point); + + OPENSSL_free(point); +} + +void EC_POINT_clear_free(EC_POINT *point) { + if (!point) { + return; + } + + ec_GFp_simple_point_clear_finish(point); + + OPENSSL_cleanse(point, sizeof *point); + OPENSSL_free(point); +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest->meth != src->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) { + return 1; + } + return ec_GFp_simple_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, 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->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_point_set_to_infinity(group, point); +} + +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_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 != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_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 != a->meth) || (a->meth != b->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return -1; + } + return ec_GFp_simple_cmp(group, a, b, ctx); +} + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_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; + + for (i = 0; i < num; i++) { + if (group->meth != points[i]->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + return ec_GFp_simple_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, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, 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->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (!ec_GFp_simple_point_set_affine_coordinates(group, point, x, y, ctx)) { + return 0; + } + + if (!EC_POINT_is_on_curve(group, point, ctx)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); + return 0; + } + + return 1; +} + +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 != r->meth) || (r->meth != a->meth) || + (a->meth != b->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_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 != r->meth) || (r->meth != a->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_dbl(group, r, a, ctx); +} + + +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) { + if (group->meth != a->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_invert(group, a, ctx); +} + +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) { + /* Previously, this function set |r| to the point at infinity if there was + * nothing to multiply. But, nobody should be calling this function with + * nothing to multiply in the first place. */ + if ((g_scalar == NULL && p_scalar == NULL) || + ((p == NULL) != (p_scalar == NULL))) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (group->meth != r->meth || + (p != NULL && group->meth != p->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + + return group->meth->mul(group, r, g_scalar, p, p_scalar, 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->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point, x, y, z, + ctx); +} + +void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {} + +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) { + return NULL; +} + +int EC_METHOD_get_field_type(const EC_METHOD *meth) { + return NID_X9_62_prime_field; +} + +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form) { + if (form != POINT_CONVERSION_UNCOMPRESSED) { + abort(); + } +} + +size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, + size_t max_num_curves) { + unsigned num_built_in_curves; + for (num_built_in_curves = 0;; num_built_in_curves++) { + if (OPENSSL_built_in_curves[num_built_in_curves].nid == NID_undef) { + break; + } + } + + unsigned i; + for (i = 0; i < max_num_curves && i < num_built_in_curves; i++) { + out_curves[i].comment = OPENSSL_built_in_curves[i].data->comment; + out_curves[i].nid = OPENSSL_built_in_curves[i].nid; + } + + return num_built_in_curves; +} diff --git a/external/boringssl/crypto/ec/ec_asn1.c b/external/boringssl/crypto/ec/ec_asn1.c new file mode 100644 index 0000000000..f31e158709 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_asn1.c @@ -0,0 +1,549 @@ +/* Written by Nils Larsch for the OpenSSL project. */ +/* ==================================================================== + * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../bytestring/internal.h" + + +static const uint8_t kParametersTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0; +static const uint8_t kPublicKeyTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1; + +EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { + CBS ec_private_key, private_key; + uint64_t version; + if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&ec_private_key, &version) || + version != 1 || + !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return NULL; + } + + /* Parse the optional parameters field. */ + EC_GROUP *inner_group = NULL; + EC_KEY *ret = NULL; + if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) { + /* Per SEC 1, as an alternative to omitting it, one is allowed to specify + * this field and put in a NULL to mean inheriting this value. This was + * omitted in a previous version of this logic without problems, so leave it + * unimplemented. */ + CBS child; + if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + inner_group = EC_KEY_parse_parameters(&child); + if (inner_group == NULL) { + goto err; + } + if (group == NULL) { + group = inner_group; + } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) { + /* If a group was supplied externally, it must match. */ + OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); + goto err; + } + if (CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + } + + if (group == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); + goto err; + } + + ret = EC_KEY_new(); + if (ret == NULL || !EC_KEY_set_group(ret, group)) { + goto err; + } + + /* Although RFC 5915 specifies the length of the key, OpenSSL historically + * got this wrong, so accept any length. See upstream's + * 30cd4ff294252c4b6a4b69cbef6a5b4117705d22. */ + ret->priv_key = + BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL); + ret->pub_key = EC_POINT_new(group); + if (ret->priv_key == NULL || ret->pub_key == NULL) { + goto err; + } + + if (BN_cmp(ret->priv_key, EC_GROUP_get0_order(group)) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + goto err; + } + + if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) { + CBS child, public_key; + uint8_t padding; + if (!CBS_get_asn1(&ec_private_key, &child, kPublicKeyTag) || + !CBS_get_asn1(&child, &public_key, CBS_ASN1_BITSTRING) || + /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then + * encoded as a BIT STRING with bits ordered as in the DER encoding. */ + !CBS_get_u8(&public_key, &padding) || + padding != 0 || + /* Explicitly check |public_key| is non-empty to save the conversion + * form later. */ + CBS_len(&public_key) == 0 || + !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key), + CBS_len(&public_key), NULL) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + + /* Save the point conversion form. + * TODO(davidben): Consider removing this. */ + ret->conv_form = (point_conversion_form_t)(CBS_data(&public_key)[0] & ~0x01); + } else { + /* Compute the public key instead. */ + if (!EC_POINT_mul(group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) { + goto err; + } + /* Remember the original private-key-only encoding. + * TODO(davidben): Consider removing this. */ + ret->enc_flag |= EC_PKEY_NO_PUBKEY; + } + + if (CBS_len(&ec_private_key) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + + /* Ensure the resulting key is valid. */ + if (!EC_KEY_check_key(ret)) { + goto err; + } + + EC_GROUP_free(inner_group); + return ret; + +err: + EC_KEY_free(ret); + EC_GROUP_free(inner_group); + return NULL; +} + +int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key, + unsigned enc_flags) { + if (key == NULL || key->group == NULL || key->priv_key == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + CBB ec_private_key, private_key; + if (!CBB_add_asn1(cbb, &ec_private_key, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&ec_private_key, 1 /* version */) || + !CBB_add_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING) || + !BN_bn2cbb_padded(&private_key, + BN_num_bytes(EC_GROUP_get0_order(key->group)), + key->priv_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + + if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) { + CBB child; + if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) || + !EC_KEY_marshal_curve_name(&child, key->group) || + !CBB_flush(&ec_private_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + } + + /* TODO(fork): replace this flexibility with sensible default? */ + if (!(enc_flags & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) { + CBB child, public_key; + if (!CBB_add_asn1(&ec_private_key, &child, kPublicKeyTag) || + !CBB_add_asn1(&child, &public_key, CBS_ASN1_BITSTRING) || + /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then + * encoded as a BIT STRING with bits ordered as in the DER encoding. */ + !CBB_add_u8(&public_key, 0 /* padding */) || + !EC_POINT_point2cbb(&public_key, key->group, key->pub_key, + key->conv_form, NULL) || + !CBB_flush(&ec_private_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + } + + if (!CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +/* is_unsigned_integer returns one if |cbs| is a valid unsigned DER INTEGER and + * zero otherwise. */ +static int is_unsigned_integer(const CBS *cbs) { + if (CBS_len(cbs) == 0) { + return 0; + } + uint8_t byte = CBS_data(cbs)[0]; + if ((byte & 0x80) || + (byte == 0 && CBS_len(cbs) > 1 && (CBS_data(cbs)[1] & 0x80) == 0)) { + /* Negative or not minimally-encoded. */ + return 0; + } + return 1; +} + +/* kPrimeFieldOID is the encoding of 1.2.840.10045.1.1. */ +static const uint8_t kPrimeField[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01}; + +static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a, + CBS *out_b, CBS *out_base_x, + CBS *out_base_y, CBS *out_order) { + /* See RFC 3279, section 2.3.5. Note that RFC 3279 calls this structure an + * ECParameters while RFC 5480 calls it a SpecifiedECDomain. */ + CBS params, field_id, field_type, curve, base; + uint64_t version; + if (!CBS_get_asn1(in, ¶ms, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(¶ms, &version) || + version != 1 || + !CBS_get_asn1(¶ms, &field_id, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) || + CBS_len(&field_type) != sizeof(kPrimeField) || + memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) != 0 || + !CBS_get_asn1(&field_id, out_prime, CBS_ASN1_INTEGER) || + !is_unsigned_integer(out_prime) || + CBS_len(&field_id) != 0 || + !CBS_get_asn1(¶ms, &curve, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&curve, out_a, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&curve, out_b, CBS_ASN1_OCTETSTRING) || + /* |curve| has an optional BIT STRING seed which we ignore. */ + !CBS_get_asn1(¶ms, &base, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(¶ms, out_order, CBS_ASN1_INTEGER) || + !is_unsigned_integer(out_order)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return 0; + } + + /* |params| has an optional cofactor which we ignore. With the optional seed + * in |curve|, a group already has arbitrarily many encodings. Parse enough to + * uniquely determine the curve. */ + + /* Require that the base point use uncompressed form. */ + uint8_t form; + if (!CBS_get_u8(&base, &form) || form != POINT_CONVERSION_UNCOMPRESSED) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM); + return 0; + } + + if (CBS_len(&base) % 2 != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return 0; + } + size_t field_len = CBS_len(&base) / 2; + CBS_init(out_base_x, CBS_data(&base), field_len); + CBS_init(out_base_y, CBS_data(&base) + field_len, field_len); + + return 1; +} + +/* integers_equal returns one if |a| and |b| are equal, up to leading zeros, and + * zero otherwise. */ +static int integers_equal(const CBS *a, const uint8_t *b, size_t b_len) { + /* Remove leading zeros from |a| and |b|. */ + CBS a_copy = *a; + while (CBS_len(&a_copy) > 0 && CBS_data(&a_copy)[0] == 0) { + CBS_skip(&a_copy, 1); + } + while (b_len > 0 && b[0] == 0) { + b++; + b_len--; + } + return CBS_mem_equal(&a_copy, b, b_len); +} + +EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) { + CBS named_curve; + if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return NULL; + } + + /* Look for a matching curve. */ + unsigned i; + for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[i]; + if (CBS_len(&named_curve) == curve->oid_len && + memcmp(CBS_data(&named_curve), curve->oid, curve->oid_len) == 0) { + return EC_GROUP_new_by_curve_name(curve->nid); + } + } + + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return NULL; +} + +int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) { + int nid = EC_GROUP_get_curve_name(group); + if (nid == NID_undef) { + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return 0; + } + + unsigned i; + for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[i]; + if (curve->nid == nid) { + CBB child; + return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) && + CBB_add_bytes(&child, curve->oid, curve->oid_len) && + CBB_flush(cbb); + } + } + + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return 0; +} + +EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) { + if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) { + return EC_KEY_parse_curve_name(cbs); + } + + /* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions + * of named curves. + * + * TODO(davidben): Remove support for this. */ + CBS prime, a, b, base_x, base_y, order; + if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y, + &order)) { + return NULL; + } + + /* Look for a matching prime curve. */ + unsigned i; + for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[i]; + const unsigned param_len = curve->data->param_len; + /* |curve->data->data| is ordered p, a, b, x, y, order, each component + * zero-padded up to the field length. Although SEC 1 states that the + * Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes + * |a| and |b|, so this comparison must allow omitting leading zeros. (This + * is relevant for P-521 whose |b| has a leading 0.) */ + if (integers_equal(&prime, curve->data->data, param_len) && + integers_equal(&a, curve->data->data + param_len, param_len) && + integers_equal(&b, curve->data->data + param_len * 2, param_len) && + integers_equal(&base_x, curve->data->data + param_len * 3, param_len) && + integers_equal(&base_y, curve->data->data + param_len * 4, param_len) && + integers_equal(&order, curve->data->data + param_len * 5, param_len)) { + return EC_GROUP_new_by_curve_name(curve->nid); + } + } + + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return NULL; +} + +EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) { + /* This function treats its |out| parameter differently from other |d2i| + * functions. If supplied, take the group from |*out|. */ + const EC_GROUP *group = NULL; + if (out != NULL && *out != NULL) { + group = EC_KEY_get0_group(*out); + } + + if (len < 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EC_KEY *ret = EC_KEY_parse_private_key(&cbs, group); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + EC_KEY_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EC_GROUP *group = EC_KEY_parse_parameters(&cbs); + if (group == NULL) { + return NULL; + } + + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL || !EC_KEY_set_group(ret, group)) { + EC_GROUP_free(group); + EC_KEY_free(ret); + return NULL; + } + EC_GROUP_free(group); + + if (out_key != NULL) { + EC_KEY_free(*out_key); + *out_key = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) { + if (key == NULL || key->group == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + CBB cbb; + if (!CBB_init(&cbb, 0) || + !EC_KEY_marshal_curve_name(&cbb, key->group)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +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, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + ret = *keyp; + if (ret->pub_key == NULL && + (ret->pub_key = EC_POINT_new(ret->group)) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + return NULL; + } + /* 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, 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, 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, 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/external/boringssl/crypto/ec/ec_key.c b/external/boringssl/crypto/ec/ec_key.c new file mode 100644 index 0000000000..fee71fed89 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_key.c @@ -0,0 +1,489 @@ +/* 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 + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); } + +EC_KEY *EC_KEY_new_method(const ENGINE *engine) { + EC_KEY *ret = OPENSSL_malloc(sizeof(EC_KEY)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, 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->conv_form = POINT_CONVERSION_UNCOMPRESSED; + ret->references = 1; + + CRYPTO_new_ex_data(&ret->ex_data); + + if (ret->ecdsa_meth && ret->ecdsa_meth->init && !ret->ecdsa_meth->init(ret)) { + CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); + if (ret->ecdsa_meth) { + METHOD_unref(ret->ecdsa_meth); + } + OPENSSL_free(ret); + return NULL; + } + + return ret; +} + +EC_KEY *EC_KEY_new_by_curve_name(int nid) { + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + 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_refcount_dec_and_test_zero(&r->references)) { + return; + } + + if (r->ecdsa_meth) { + if (r->ecdsa_meth->finish) { + r->ecdsa_meth->finish(r); + } + METHOD_unref(r->ecdsa_meth); + } + + EC_GROUP_free(r->group); + EC_POINT_free(r->pub_key); + BN_clear_free(r->priv_key); + + CRYPTO_free_ex_data(&g_ex_data_class, 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, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + /* Copy the parameters. */ + if (src->group) { + /* TODO(fork): duplicating the group seems wasteful. */ + EC_GROUP_free(dest->group); + dest->group = EC_GROUP_dup(src->group); + if (dest->group == NULL) { + return NULL; + } + } + + /* Copy the public key. */ + if (src->pub_key && src->group) { + EC_POINT_free(dest->pub_key); + dest->pub_key = EC_POINT_dup(src->pub_key, src->group); + if (dest->pub_key == NULL) { + 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 */ + if (src->ecdsa_meth) { + METHOD_unref(dest->ecdsa_meth); + dest->ecdsa_meth = src->ecdsa_meth; + METHOD_ref(dest->ecdsa_meth); + } + CRYPTO_free_ex_data(&g_ex_data_class, dest, &dest->ex_data); + if (!CRYPTO_dup_ex_data(&g_ex_data_class, &dest->ex_data, + &src->ex_data)) { + return NULL; + } + + /* copy the rest */ + dest->enc_flag = src->enc_flag; + dest->conv_form = src->conv_form; + + 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) { + CRYPTO_refcount_inc(&r->references); + return 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) { + 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); + if (key->group == NULL) { + return 0; + } + /* XXX: |BN_cmp| is not constant time. */ + if (key->priv_key != NULL && + BN_cmp(key->priv_key, EC_GROUP_get0_order(group)) >= 0) { + return 0; + } + return 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) { + /* XXX: |BN_cmp| is not constant time. */ + if (key->group != NULL && + BN_cmp(priv_key, EC_GROUP_get0_order(key->group)) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + return 0; + } + 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) { + 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_check_key(const EC_KEY *eckey) { + int ok = 0; + BN_CTX *ctx = NULL; + EC_POINT *point = NULL; + + if (!eckey || !eckey->group || !eckey->pub_key) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + goto err; + } + + ctx = BN_CTX_new(); + + if (ctx == 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_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + /* TODO(fork): can this be skipped if the cofactor is one or if we're about + * to check the private key, below? */ + if (eckey->group->meth->check_pub_key_order != NULL && + !eckey->group->meth->check_pub_key_order(eckey->group, eckey->pub_key, + ctx)) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + goto err; + } + /* in case the priv_key is present : + * check if generator * priv_key == pub_key + */ + if (eckey->priv_key) { + /* XXX: |BN_cmp| is not constant time. */ + if (BN_cmp(eckey->priv_key, EC_GROUP_get0_order(eckey->group)) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + goto err; + } + point = EC_POINT_new(eckey->group); + if (point == NULL || + !EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY); + goto err; + } + } + ok = 1; + +err: + BN_CTX_free(ctx); + 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, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ctx = BN_CTX_new(); + + if (ctx == NULL) { + return 0; + } + + BN_CTX_start(ctx); + point = EC_POINT_new(key->group); + + if (point == NULL) { + goto err; + } + + tx = BN_CTX_get(ctx); + ty = BN_CTX_get(ctx); + if (tx == NULL || + ty == NULL) { + goto err; + } + + 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_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: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(point); + return ok; +} + +int EC_KEY_generate_key(EC_KEY *eckey) { + int ok = 0; + BIGNUM *priv_key = NULL; + EC_POINT *pub_key = NULL; + + if (!eckey || !eckey->group) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (eckey->priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) { + goto err; + } + } else { + priv_key = eckey->priv_key; + } + + const BIGNUM *order = EC_GROUP_get0_order(eckey->group); + 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, NULL)) { + goto err; + } + + eckey->priv_key = priv_key; + eckey->pub_key = pub_key; + + ok = 1; + +err: + if (eckey->pub_key == NULL) { + EC_POINT_free(pub_key); + } + if (eckey->priv_key == NULL) { + BN_free(priv_key); + } + return ok; +} + +int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +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); +} + +void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) {} diff --git a/external/boringssl/crypto/ec/ec_montgomery.c b/external/boringssl/crypto/ec/ec_montgomery.c new file mode 100644 index 0000000000..35df365126 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_montgomery.c @@ -0,0 +1,323 @@ +/* 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 + +#include +#include +#include + +#include "internal.h" + + +int ec_GFp_mont_group_init(EC_GROUP *group) { + int ok; + + ok = ec_GFp_simple_group_init(group); + group->mont = NULL; + return ok; +} + +void ec_GFp_mont_group_finish(EC_GROUP *group) { + BN_MONT_CTX_free(group->mont); + group->mont = NULL; + ec_GFp_simple_group_finish(group); +} + +int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) { + BN_MONT_CTX_free(dest->mont); + dest->mont = NULL; + + if (!ec_GFp_simple_group_copy(dest, src)) { + return 0; + } + + if (src->mont != NULL) { + dest->mont = BN_MONT_CTX_new(); + if (dest->mont == NULL) { + return 0; + } + if (!BN_MONT_CTX_copy(dest->mont, src->mont)) { + goto err; + } + } + + return 1; + +err: + BN_MONT_CTX_free(dest->mont); + dest->mont = 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; + int ret = 0; + + BN_MONT_CTX_free(group->mont); + group->mont = 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, ERR_R_BN_LIB); + goto err; + } + + group->mont = mont; + mont = NULL; + + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + + if (!ret) { + BN_MONT_CTX_free(group->mont); + group->mont = NULL; + } + +err: + BN_CTX_free(new_ctx); + 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->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, b, group->mont, ctx); +} + +int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { + if (group->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, a, group->mont, ctx); +} + +int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { + if (group->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_to_montgomery(r, a, group->mont, ctx); +} + +int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { + if (group->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_from_montgomery(r, a, group->mont, ctx); +} + +static int ec_GFp_mont_check_pub_key_order(const EC_GROUP *group, + const EC_POINT* pub_key, + BN_CTX *ctx) { + EC_POINT *point = EC_POINT_new(group); + int ret = 0; + + if (point == NULL || + !ec_wNAF_mul(group, point, NULL, pub_key, EC_GROUP_get0_order(group), + ctx) || + !EC_POINT_is_at_infinity(group, point)) { + goto err; + } + + ret = 1; + +err: + EC_POINT_free(point); + return ret; +} + +static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + + BN_CTX *new_ctx = NULL; + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + int ret = 0; + + BN_CTX_start(ctx); + + if (BN_cmp(&point->Z, &group->one) == 0) { + /* |point| is already affine. */ + if (x != NULL && !BN_from_montgomery(x, &point->X, group->mont, ctx)) { + goto err; + } + if (y != NULL && !BN_from_montgomery(y, &point->Y, group->mont, ctx)) { + goto err; + } + } else { + /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ + + BIGNUM *Z_1 = BN_CTX_get(ctx); + BIGNUM *Z_2 = BN_CTX_get(ctx); + BIGNUM *Z_3 = BN_CTX_get(ctx); + if (Z_1 == NULL || + Z_2 == NULL || + Z_3 == NULL) { + goto err; + } + + /* The straightforward way to calculate the inverse of a Montgomery-encoded + * value where the result is Montgomery-encoded is: + * + * |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|. + * + * This is equivalent, but more efficient, because |BN_from_montgomery| + * is more efficient (at least in theory) than |BN_to_montgomery|, since it + * doesn't have to do the multiplication before the reduction. */ + if (!BN_from_montgomery(Z_1, &point->Z, group->mont, ctx) || + !BN_from_montgomery(Z_1, Z_1, group->mont, ctx) || + !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) { + goto err; + } + + if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, group->mont, ctx)) { + goto err; + } + + /* Instead of using |BN_from_montgomery| to convert the |x| coordinate + * and then calling |BN_from_montgomery| again to convert the |y| + * coordinate below, convert the common factor |Z_2| once now, saving one + * reduction. */ + if (!BN_from_montgomery(Z_2, Z_2, group->mont, ctx)) { + goto err; + } + + if (x != NULL) { + if (!BN_mod_mul_montgomery(x, &point->X, Z_2, group->mont, ctx)) { + goto err; + } + } + + if (y != NULL) { + if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, group->mont, ctx) || + !BN_mod_mul_montgomery(y, &point->Y, Z_3, group->mont, ctx)) { + goto err; + } + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +const EC_METHOD *EC_GFp_mont_method(void) { + static const EC_METHOD ret = { + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve, + ec_GFp_mont_point_get_affine_coordinates, + ec_wNAF_mul /* XXX: Not constant time. */, + ec_GFp_mont_check_pub_key_order, + ec_GFp_mont_field_mul, + ec_GFp_mont_field_sqr, + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + }; + + return &ret; +} diff --git a/external/boringssl/crypto/ec/ec_test.cc b/external/boringssl/crypto/ec/ec_test.cc new file mode 100644 index 0000000000..ce9d99f3b4 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_test.cc @@ -0,0 +1,520 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field +// omitted. +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, +}; + +// kECKeySpecifiedCurve is the above key with P-256's parameters explicitly +// spelled out rather than using a named curve. +static const uint8_t kECKeySpecifiedCurve[] = { + 0x30, 0x82, 0x01, 0x22, 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, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02, + 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, + 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, + 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, + 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, + 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, + 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, + 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, + 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, + 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, +}; + +// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where +// the private key is one. The private key is incorrectly encoded without zero +// padding. +static const uint8_t kECKeyMissingZeros[] = { + 0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, + 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, + 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, + 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, + 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, +}; + +// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where +// the private key is one. The private key is encoded with the required zero +// padding. +static const uint8_t kECKeyWithZeros[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, + 0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, + 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, + 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, + 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, + 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, +}; + +// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the +// result or nullptr on error. +static ScopedEC_KEY DecodeECPrivateKey(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + ScopedEC_KEY ret(EC_KEY_parse_private_key(&cbs, NULL)); + if (!ret || CBS_len(&cbs) != 0) { + return nullptr; + } + return ret; +} + +// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It +// returns true on success or false on error. +static bool EncodeECPrivateKey(std::vector *out, const EC_KEY *key) { + ScopedCBB cbb; + uint8_t *der; + size_t der_len; + if (!CBB_init(cbb.get(), 0) || + !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + out->assign(der, der + der_len); + OPENSSL_free(der); + return true; +} + +static bool Testd2i_ECPrivateKey() { + ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithoutPublic, + sizeof(kECKeyWithoutPublic)); + if (!key) { + fprintf(stderr, "Failed to parse private key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + std::vector out; + if (!EncodeECPrivateKey(&out, key.get())) { + fprintf(stderr, "Failed to serialize private key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (std::vector(kECKeyWithoutPublic, + kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) != + out) { + fprintf(stderr, "Serialisation of key doesn't match original.\n"); + return false; + } + + const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get()); + if (pub_key == NULL) { + fprintf(stderr, "Public key missing.\n"); + return false; + } + + ScopedBIGNUM x(BN_new()); + ScopedBIGNUM y(BN_new()); + if (!x || !y) { + return false; + } + if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()), + pub_key, x.get(), y.get(), NULL)) { + fprintf(stderr, "Failed to get public key in affine coordinates.\n"); + return false; + } + ScopedOpenSSLString x_hex(BN_bn2hex(x.get())); + ScopedOpenSSLString y_hex(BN_bn2hex(y.get())); + if (!x_hex || !y_hex) { + return false; + } + if (0 != strcmp( + x_hex.get(), + "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") || + 0 != strcmp( + y_hex.get(), + "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) { + fprintf(stderr, "Incorrect public key: %s %s\n", x_hex.get(), y_hex.get()); + return false; + } + + return true; +} + +static bool TestZeroPadding() { + // Check that the correct encoding round-trips. + ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithZeros, + sizeof(kECKeyWithZeros)); + std::vector out; + if (!key || !EncodeECPrivateKey(&out, key.get())) { + ERR_print_errors_fp(stderr); + return false; + } + + if (std::vector(kECKeyWithZeros, + kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) { + fprintf(stderr, "Serialisation of key was incorrect.\n"); + return false; + } + + // Keys without leading zeros also parse, but they encode correctly. + key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros)); + if (!key || !EncodeECPrivateKey(&out, key.get())) { + ERR_print_errors_fp(stderr); + return false; + } + + if (std::vector(kECKeyWithZeros, + kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) { + fprintf(stderr, "Serialisation of key was incorrect.\n"); + return false; + } + + return true; +} + +static bool TestSpecifiedCurve() { + // Test keys with specified curves may be decoded. + ScopedEC_KEY key = + DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve)); + if (!key) { + ERR_print_errors_fp(stderr); + return false; + } + + // The group should have been interpreted as P-256. + if (EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())) != + NID_X9_62_prime256v1) { + fprintf(stderr, "Curve name incorrect.\n"); + return false; + } + + // Encoding the key should still use named form. + std::vector out; + if (!EncodeECPrivateKey(&out, key.get())) { + ERR_print_errors_fp(stderr); + return false; + } + if (std::vector(kECKeyWithoutPublic, + kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) != + out) { + fprintf(stderr, "Serialisation of key was incorrect.\n"); + return false; + } + + return true; +} + +static bool TestSetAffine(const int nid) { + ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid)); + if (!key) { + return false; + } + + const EC_GROUP *const group = EC_KEY_get0_group(key.get()); + + if (!EC_KEY_generate_key(key.get())) { + fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + if (!EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), + nullptr)) { + fprintf(stderr, "generated point is not on curve with nid %d", nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedBIGNUM x(BN_new()); + ScopedBIGNUM y(BN_new()); + if (!EC_POINT_get_affine_coordinates_GFp(group, + EC_KEY_get0_public_key(key.get()), + x.get(), y.get(), nullptr)) { + fprintf(stderr, "EC_POINT_get_affine_coordinates_GFp failed with nid %d\n", + nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedEC_POINT point(EC_POINT_new(group)); + if (!point) { + return false; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(), y.get(), + nullptr)) { + fprintf(stderr, "EC_POINT_set_affine_coordinates_GFp failed with nid %d\n", + nid); + ERR_print_errors_fp(stderr); + return false; + } + + // Subtract one from |y| to make the point no longer on the curve. + if (!BN_sub(y.get(), y.get(), BN_value_one())) { + return false; + } + + ScopedEC_POINT invalid_point(EC_POINT_new(group)); + if (!invalid_point) { + return false; + } + + if (EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), x.get(), + y.get(), nullptr)) { + fprintf(stderr, + "EC_POINT_set_affine_coordinates_GFp succeeded with invalid " + "coordinates with nid %d\n", + nid); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestArbitraryCurve() { + // Make a P-256 key and extract the affine coordinates. + ScopedEC_KEY key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (!key || !EC_KEY_generate_key(key.get())) { + return false; + } + + // Make an arbitrary curve which is identical to P-256. + static const uint8_t kP[] = { + 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, + }; + static const uint8_t kA[] = { + 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, + }; + static const uint8_t kB[] = { + 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, + }; + static const uint8_t kX[] = { + 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, + }; + static const uint8_t kY[] = { + 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, + }; + static const uint8_t kOrder[] = { + 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, + }; + ScopedBN_CTX ctx(BN_CTX_new()); + ScopedBIGNUM p(BN_bin2bn(kP, sizeof(kP), nullptr)); + ScopedBIGNUM a(BN_bin2bn(kA, sizeof(kA), nullptr)); + ScopedBIGNUM b(BN_bin2bn(kB, sizeof(kB), nullptr)); + ScopedBIGNUM gx(BN_bin2bn(kX, sizeof(kX), nullptr)); + ScopedBIGNUM gy(BN_bin2bn(kY, sizeof(kY), nullptr)); + ScopedBIGNUM order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); + ScopedBIGNUM cofactor(BN_new()); + if (!ctx || !p || !a || !b || !gx || !gy || !order || !cofactor || + !BN_set_word(cofactor.get(), 1)) { + return false; + } + + ScopedEC_GROUP group( + EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); + if (!group) { + return false; + } + ScopedEC_POINT generator(EC_POINT_new(group.get())); + if (!generator || + !EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), + gx.get(), gy.get(), ctx.get()) || + !EC_GROUP_set_generator(group.get(), generator.get(), order.get(), + cofactor.get())) { + return false; + } + + // |group| should not have a curve name. + if (EC_GROUP_get_curve_name(group.get()) != NID_undef) { + return false; + } + + // Copy |key| to |key2| using |group|. + ScopedEC_KEY key2(EC_KEY_new()); + ScopedEC_POINT point(EC_POINT_new(group.get())); + ScopedBIGNUM x(BN_new()), y(BN_new()); + if (!key2 || !point || !x || !y || + !EC_KEY_set_group(key2.get(), group.get()) || + !EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) || + !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()), + EC_KEY_get0_public_key(key.get()), + x.get(), y.get(), nullptr) || + !EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(), + y.get(), nullptr) || + !EC_KEY_set_public_key(key2.get(), point.get())) { + fprintf(stderr, "Could not copy key.\n"); + return false; + } + + // The key must be valid according to the new group too. + if (!EC_KEY_check_key(key2.get())) { + fprintf(stderr, "Copied key is not valid.\n"); + return false; + } + + // Repeat the process for |EC_GROUP_new_arbitrary|. + group.reset(EC_GROUP_new_arbitrary(p.get(), a.get(), b.get(), gx.get(), + gy.get(), order.get(), cofactor.get())); + if (!group) { + return false; + } + + // |group| should not have a curve name. + if (EC_GROUP_get_curve_name(group.get()) != NID_undef) { + return false; + } + + // Copy |key| to |key2| using |group|. + key2.reset(EC_KEY_new()); + point.reset(EC_POINT_new(group.get())); + if (!key2 || !point || + !EC_KEY_set_group(key2.get(), group.get()) || + !EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) || + !EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(), + y.get(), nullptr) || + !EC_KEY_set_public_key(key2.get(), point.get())) { + fprintf(stderr, "Could not copy key.\n"); + return false; + } + + // The key must be valid according to the new group too. + if (!EC_KEY_check_key(key2.get())) { + fprintf(stderr, "Copied key is not valid.\n"); + return false; + } + + return true; +} + +static bool TestAddingEqualPoints(int nid) { + ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid)); + if (!key) { + return false; + } + + const EC_GROUP *const group = EC_KEY_get0_group(key.get()); + + if (!EC_KEY_generate_key(key.get())) { + fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedEC_POINT p1(EC_POINT_new(group)); + ScopedEC_POINT p2(EC_POINT_new(group)); + ScopedEC_POINT double_p1(EC_POINT_new(group)); + ScopedEC_POINT p1_plus_p2(EC_POINT_new(group)); + if (!p1 || !p2 || !double_p1 || !p1_plus_p2) { + return false; + } + + if (!EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())) || + !EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))) { + fprintf(stderr, "EC_POINT_COPY failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedBN_CTX ctx(BN_CTX_new()); + if (!ctx) { + return false; + } + + if (!EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()) || + !EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())) { + fprintf(stderr, "Point operation failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + if (EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()) != 0) { + fprintf(stderr, "A+A != 2A for nid %d", nid); + return false; + } + + return true; +} + +static bool ForEachCurve(bool (*test_func)(int nid)) { + const size_t num_curves = EC_get_builtin_curves(nullptr, 0); + std::vector curves(num_curves); + EC_get_builtin_curves(curves.data(), num_curves); + + for (const auto& curve : curves) { + if (!test_func(curve.nid)) { + fprintf(stderr, "Test failed for %s\n", curve.comment); + return false; + } + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!Testd2i_ECPrivateKey() || + !TestZeroPadding() || + !TestSpecifiedCurve() || + !ForEachCurve(TestSetAffine) || + !ForEachCurve(TestAddingEqualPoints) || + !TestArbitraryCurve()) { + fprintf(stderr, "failed\n"); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/ec/example_mul.c b/external/boringssl/crypto/ec/example_mul.c new file mode 100644 index 0000000000..a2bdd5277e --- /dev/null +++ b/external/boringssl/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 + +#include +#include +#include +#include + + +static 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/external/boringssl/crypto/ec/internal.h b/external/boringssl/crypto/ec/internal.h new file mode 100644 index 0000000000..f2cbb96191 --- /dev/null +++ b/external/boringssl/crypto/ec/internal.h @@ -0,0 +1,288 @@ +/* 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 + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +struct ec_method_st { + int (*group_init)(EC_GROUP *); + void (*group_finish)(EC_GROUP *); + int (*group_copy)(EC_GROUP *, const EC_GROUP *); + int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); + + /* Computes |r = g_scalar*generator + p_scalar*p| if |g_scalar| and |p_scalar| + * are both non-null. Computes |r = g_scalar*generator| if |p_scalar| is null. + * Computes |r = p_scalar*p| if g_scalar is null. At least one of |g_scalar| + * and |p_scalar| must be non-null, and |p| must be non-null if |p_scalar| is + * non-null. */ + int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx); + + /* |check_pub_key_order| checks that the public key is in the proper subgroup + * by checking that |pub_key*group->order| is the point at infinity. This may + * be NULL for |EC_METHOD|s specialized for prime-order curves (i.e. with + * cofactor one), as this check is not necessary for such curves (See section + * A.3 of the NSA's "Suite B Implementer's Guide to FIPS 186-3 + * (ECDSA)"). */ + int (*check_pub_key_order)(const EC_GROUP *group, const EC_POINT *pub_key, + BN_CTX *ctx); + + /* 'field_mul' and 'field_sqr' 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_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 */ +} /* EC_METHOD */; + +const EC_METHOD* EC_GFp_mont_method(void); + +struct ec_group_st { + const EC_METHOD *meth; + + EC_POINT *generator; + BIGNUM order, cofactor; + + int curve_name; /* optional NID for named curve */ + + const BN_MONT_CTX *mont_data; /* data for ECDSA inverse */ + + /* The following members are handled by the method functions, + * even if they appear generic */ + + BIGNUM field; /* For curves over GF(p), this is the modulus. */ + + BIGNUM a, b; /* Curve coefficients. */ + + int a_is_minus3; /* enable optimized point arithmetics for special case */ + + BN_MONT_CTX *mont; /* Montgomery structure. */ + + BIGNUM one; /* The value one. */ +} /* EC_GROUP */; + +struct ec_point_st { + const EC_METHOD *meth; + + BIGNUM X; + BIGNUM Y; + BIGNUM Z; /* Jacobian projective coordinates: + * (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */ +} /* EC_POINT */; + +EC_GROUP *ec_group_new(const EC_METHOD *meth); +int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src); + +/* ec_group_get_mont_data returns a Montgomery context for operations in the + * scalar field of |group|. It may return NULL in the case that |group| is not + * a built-in group. */ +const BN_MONT_CTX *ec_group_get_mont_data(const EC_GROUP *group); + +int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx); + +/* method functions in simple.c */ +int ec_GFp_simple_group_init(EC_GROUP *); +void ec_GFp_simple_group_finish(EC_GROUP *); +int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); +unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *); +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_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 *); +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_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx); + +void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in); + +const EC_METHOD *EC_GFp_nistp224_method(void); +const EC_METHOD *EC_GFp_nistp256_method(void); + +/* Returns GFp methods using montgomery multiplication, with x86-64 + * optimized P256. See http://eprint.iacr.org/2013/816. */ +const EC_METHOD *EC_GFp_nistz256_method(void); + +struct ec_key_st { + EC_GROUP *group; + + EC_POINT *pub_key; + BIGNUM *priv_key; + + unsigned int enc_flag; + point_conversion_form_t conv_form; + + CRYPTO_refcount_t references; + + 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; + uint8_t oid[8]; + uint8_t oid_len; + 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/external/boringssl/crypto/ec/oct.c b/external/boringssl/crypto/ec/oct.c new file mode 100644 index 0000000000..bf1957cade --- /dev/null +++ b/external/boringssl/crypto/ec/oct.c @@ -0,0 +1,428 @@ +/* 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 + +#include +#include +#include + +#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_R_INVALID_FORM); + goto err; + } + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + goto err; + } + + /* 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_R_BUFFER_TOO_SMALL); + goto err; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + } + + 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, 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, ERR_R_INTERNAL_ERROR); + goto err; + } + i += field_len; + } + + if (i != ret) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (used_ctx) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; + +err: + if (used_ctx) { + BN_CTX_end(ctx); + } + 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_R_BUFFER_TOO_SMALL); + return 0; + } + form = buf[0]; + y_bit = form & 1; + form = form & ~1U; + if ((form != POINT_CONVERSION_COMPRESSED && + form != POINT_CONVERSION_UNCOMPRESSED) || + (form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); + return 0; + } + + 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_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 (x == NULL || 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_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_R_INVALID_ENCODING); + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + goto err; + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + 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 != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_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 != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); +} + +int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, BN_CTX *ctx) { + size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx); + if (len == 0) { + return 0; + } + uint8_t *p; + return CBB_add_space(out, &p, len) && + EC_POINT_point2oct(group, point, form, p, len, ctx) == len; +} + +int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) { + if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT); + return 0; + } + + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *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); + 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 (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_R_INVALID_COMPRESSED_POINT); + } else { + OPENSSL_PUT_ERROR(EC, 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_R_INVALID_COMPRESSION_BIT); + } else { + /* BN_mod_sqrt() should have cought this error (not a square) */ + OPENSSL_PUT_ERROR(EC, 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, 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); + 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->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_set_compressed_coordinates(group, point, x, y_bit, ctx); +} diff --git a/external/boringssl/crypto/ec/p224-64.c b/external/boringssl/crypto/ec/p224-64.c new file mode 100644 index 0000000000..7bf889c969 --- /dev/null +++ b/external/boringssl/crypto/ec/p224-64.c @@ -0,0 +1,1198 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* A 64-bit implementation of the NIST P-224 elliptic curve point multiplication + * + * Inspired by Daniel J. Bernstein's public domain nistp224 implementation + * and Adam Langley's public domain 64-bit C implementation of curve25519. */ + +#include + +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) && \ + !defined(OPENSSL_SMALL) + +#include +#include +#include +#include + +#include + +#include "internal.h" +#include "../internal.h" + + +typedef uint8_t u8; +typedef uint64_t u64; +typedef int64_t s64; + +/* Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3 + * using 64-bit coefficients called 'limbs', and sometimes (for multiplication + * results) as b_0 + 2^56*b_1 + 2^112*b_2 + 2^168*b_3 + 2^224*b_4 + 2^280*b_5 + + * 2^336*b_6 using 128-bit coefficients called 'widelimbs'. A 4-limb + * representation is an 'felem'; a 7-widelimb representation is a 'widefelem'. + * Even within felems, bits of adjacent limbs overlap, and we don't always + * reduce the representations: we ensure that inputs to each felem + * multiplication satisfy a_i < 2^60, so outputs satisfy b_i < 4*2^60*2^60, and + * fit into a 128-bit word without overflow. The coefficients are then again + * partially reduced to obtain an felem satisfying a_i < 2^57. We only reduce + * to the unique minimal representation at the end of the computation. */ + +typedef uint64_t limb; +typedef uint128_t widelimb; + +typedef limb felem[4]; +typedef widelimb widefelem[7]; + +/* Field element represented as a byte arrary. 28*8 = 224 bits is also the + * group order size for the elliptic curve, and we also use this type for + * scalars for point multiplication. */ +typedef u8 felem_bytearray[28]; + +/* Precomputed multiples of the standard generator + * Points are given in coordinates (X, Y, Z) where Z normally is 1 + * (0 for the point at infinity). + * For each field element, slice a_0 is word 0, etc. + * + * The table has 2 * 16 elements, starting with the following: + * index | bits | point + * ------+---------+------------------------------ + * 0 | 0 0 0 0 | 0G + * 1 | 0 0 0 1 | 1G + * 2 | 0 0 1 0 | 2^56G + * 3 | 0 0 1 1 | (2^56 + 1)G + * 4 | 0 1 0 0 | 2^112G + * 5 | 0 1 0 1 | (2^112 + 1)G + * 6 | 0 1 1 0 | (2^112 + 2^56)G + * 7 | 0 1 1 1 | (2^112 + 2^56 + 1)G + * 8 | 1 0 0 0 | 2^168G + * 9 | 1 0 0 1 | (2^168 + 1)G + * 10 | 1 0 1 0 | (2^168 + 2^56)G + * 11 | 1 0 1 1 | (2^168 + 2^56 + 1)G + * 12 | 1 1 0 0 | (2^168 + 2^112)G + * 13 | 1 1 0 1 | (2^168 + 2^112 + 1)G + * 14 | 1 1 1 0 | (2^168 + 2^112 + 2^56)G + * 15 | 1 1 1 1 | (2^168 + 2^112 + 2^56 + 1)G + * followed by a copy of this with each element multiplied by 2^28. + * + * The reason for this is so that we can clock bits into four different + * locations when doing simple scalar multiplies against the base point, + * and then another four locations using the second 16 elements. */ +static const felem g_pre_comp[2][16][3] = { + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0x3280d6115c1d21, 0xc1d356c2112234, 0x7f321390b94a03, 0xb70e0cbd6bb4bf}, + {0xd5819985007e34, 0x75a05a07476444, 0xfb4c22dfe6cd43, 0xbd376388b5f723}, + {1, 0, 0, 0}}, + {{0xfd9675666ebbe9, 0xbca7664d40ce5e, 0x2242df8d8a2a43, 0x1f49bbb0f99bc5}, + {0x29e0b892dc9c43, 0xece8608436e662, 0xdc858f185310d0, 0x9812dd4eb8d321}, + {1, 0, 0, 0}}, + {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, 0x16e9a3bbce8a3f, 0xeedcccd8c2a748}, + {0xf19f90ed50266d, 0xabf2b4bf65f9df, 0x313865468fafec, 0x5cb379ba910a17}, + {1, 0, 0, 0}}, + {{0x0641966cab26e3, 0x91fb2991fab0a0, 0xefec27a4e13a0b, 0x0499aa8a5f8ebe}, + {0x7510407766af5d, 0x84d929610d5450, 0x81d77aae82f706, 0x6916f6d4338c5b}, + {1, 0, 0, 0}}, + {{0xea95ac3b1f15c6, 0x086000905e82d4, 0xdd323ae4d1c8b1, 0x932b56be7685a3}, + {0x9ef93dea25dbbf, 0x41665960f390f0, 0xfdec76dbe2a8a7, 0x523e80f019062a}, + {1, 0, 0, 0}}, + {{0x822fdd26732c73, 0xa01c83531b5d0f, 0x363f37347c1ba4, 0xc391b45c84725c}, + {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, 0xc393da7e222a7f, 0x1efb7890ede244}, + {1, 0, 0, 0}}, + {{0x4c9e90ca217da1, 0xd11beca79159bb, 0xff8d33c2c98b7c, 0x2610b39409f849}, + {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, 0x966c079b753c89, 0xfe67e4e820b112}, + {1, 0, 0, 0}}, + {{0xe28cae2df5312d, 0xc71b61d16f5c6e, 0x79b7619a3e7c4c, 0x05c73240899b47}, + {0x9f7f6382c73e3a, 0x18615165c56bda, 0x641fab2116fd56, 0x72855882b08394}, + {1, 0, 0, 0}}, + {{0x0469182f161c09, 0x74a98ca8d00fb5, 0xb89da93489a3e0, 0x41c98768fb0c1d}, + {0xe5ea05fb32da81, 0x3dce9ffbca6855, 0x1cfe2d3fbf59e6, 0x0e5e03408738a7}, + {1, 0, 0, 0}}, + {{0xdab22b2333e87f, 0x4430137a5dd2f6, 0xe03ab9f738beb8, 0xcb0c5d0dc34f24}, + {0x764a7df0c8fda5, 0x185ba5c3fa2044, 0x9281d688bcbe50, 0xc40331df893881}, + {1, 0, 0, 0}}, + {{0xb89530796f0f60, 0xade92bd26909a3, 0x1a0c83fb4884da, 0x1765bf22a5a984}, + {0x772a9ee75db09e, 0x23bc6c67cec16f, 0x4c1edba8b14e2f, 0xe2a215d9611369}, + {1, 0, 0, 0}}, + {{0x571e509fb5efb3, 0xade88696410552, 0xc8ae85fada74fe, 0x6c7e4be83bbde3}, + {0xff9f51160f4652, 0xb47ce2495a6539, 0xa2946c53b582f4, 0x286d2db3ee9a60}, + {1, 0, 0, 0}}, + {{0x40bbd5081a44af, 0x0995183b13926c, 0xbcefba6f47f6d0, 0x215619e9cc0057}, + {0x8bc94d3b0df45e, 0xf11c54a3694f6f, 0x8631b93cdfe8b5, 0xe7e3f4b0982db9}, + {1, 0, 0, 0}}, + {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, 0x1c29819435d2c6, 0xc813132f4c07e9}, + {0x2891425503b11f, 0x08781030579fea, 0xf5426ba5cc9674, 0x1e28ebf18562bc}, + {1, 0, 0, 0}}, + {{0x9f31997cc864eb, 0x06cd91d28b5e4c, 0xff17036691a973, 0xf1aef351497c58}, + {0xdd1f2d600564ff, 0xdead073b1402db, 0x74a684435bd693, 0xeea7471f962558}, + {1, 0, 0, 0}}}, + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31}, + {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d}, + {1, 0, 0, 0}}, + {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3}, + {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a}, + {1, 0, 0, 0}}, + {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33}, + {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100}, + {1, 0, 0, 0}}, + {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5}, + {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea}, + {1, 0, 0, 0}}, + {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be}, + {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51}, + {1, 0, 0, 0}}, + {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1}, + {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb}, + {1, 0, 0, 0}}, + {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233}, + {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def}, + {1, 0, 0, 0}}, + {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae}, + {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45}, + {1, 0, 0, 0}}, + {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e}, + {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb}, + {1, 0, 0, 0}}, + {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de}, + {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3}, + {1, 0, 0, 0}}, + {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05}, + {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58}, + {1, 0, 0, 0}}, + {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb}, + {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0}, + {1, 0, 0, 0}}, + {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9}, + {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea}, + {1, 0, 0, 0}}, + {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba}, + {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405}, + {1, 0, 0, 0}}, + {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e}, + {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e}, + {1, 0, 0, 0}}}}; + +/* Helper functions to convert field elements to/from internal representation */ +static void bin28_to_felem(felem out, const u8 in[28]) { + out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff; + out[1] = (*((const uint64_t *)(in + 7))) & 0x00ffffffffffffff; + out[2] = (*((const uint64_t *)(in + 14))) & 0x00ffffffffffffff; + out[3] = (*((const uint64_t *)(in + 20))) >> 8; +} + +static void felem_to_bin28(u8 out[28], const felem in) { + size_t i; + for (i = 0; i < 7; ++i) { + out[i] = in[0] >> (8 * i); + out[i + 7] = in[1] >> (8 * i); + out[i + 14] = in[2] >> (8 * i); + out[i + 21] = in[3] >> (8 * i); + } +} + +/* To preserve endianness when using BN_bn2bin and BN_bin2bn */ +static void flip_endian(u8 *out, const u8 *in, size_t len) { + size_t i; + for (i = 0; i < len; ++i) { + out[i] = in[len - 1 - i]; + } +} + +/* From OpenSSL BIGNUM to internal representation */ +static int BN_to_felem(felem out, const BIGNUM *bn) { + /* BN_bn2bin eats leading zeroes */ + felem_bytearray b_out; + memset(b_out, 0, sizeof(b_out)); + size_t num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof(b_out) || + BN_is_negative(bn)) { + OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + + felem_bytearray b_in; + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin28_to_felem(out, b_out); + return 1; +} + +/* From internal representation to OpenSSL BIGNUM */ +static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) { + felem_bytearray b_in, b_out; + felem_to_bin28(b_in, in); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); +} + +/* Field operations, using the internal representation of field elements. + * NB! These operations are specific to our point multiplication and cannot be + * expected to be correct in general - e.g., multiplication with a large scalar + * will cause an overflow. */ + +static void felem_assign(felem out, const felem in) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* Sum two field elements: out += in */ +static void felem_sum(felem out, const felem in) { + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* Get negative value: out = -in */ +/* Assumes in[i] < 2^57 */ +static void felem_neg(felem out, const felem in) { + static const limb two58p2 = (((limb)1) << 58) + (((limb)1) << 2); + static const limb two58m2 = (((limb)1) << 58) - (((limb)1) << 2); + static const limb two58m42m2 = + (((limb)1) << 58) - (((limb)1) << 42) - (((limb)1) << 2); + + /* Set to 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] = two58p2 - in[0]; + out[1] = two58m42m2 - in[1]; + out[2] = two58m2 - in[2]; + out[3] = two58m2 - in[3]; +} + +/* Subtract field elements: out -= in */ +/* Assumes in[i] < 2^57 */ +static void felem_diff(felem out, const felem in) { + static const limb two58p2 = (((limb)1) << 58) + (((limb)1) << 2); + static const limb two58m2 = (((limb)1) << 58) - (((limb)1) << 2); + static const limb two58m42m2 = + (((limb)1) << 58) - (((limb)1) << 42) - (((limb)1) << 2); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two58p2; + out[1] += two58m42m2; + out[2] += two58m2; + out[3] += two58m2; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* Subtract in unreduced 128-bit mode: out -= in */ +/* Assumes in[i] < 2^119 */ +static void widefelem_diff(widefelem out, const widefelem in) { + static const widelimb two120 = ((widelimb)1) << 120; + static const widelimb two120m64 = + (((widelimb)1) << 120) - (((widelimb)1) << 64); + static const widelimb two120m104m64 = + (((widelimb)1) << 120) - (((widelimb)1) << 104) - (((widelimb)1) << 64); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two120; + out[1] += two120m64; + out[2] += two120m64; + out[3] += two120; + out[4] += two120m104m64; + out[5] += two120m64; + out[6] += two120m64; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; +} + +/* Subtract in mixed mode: out128 -= in64 */ +/* in[i] < 2^63 */ +static void felem_diff_128_64(widefelem out, const felem in) { + static const widelimb two64p8 = (((widelimb)1) << 64) + (((widelimb)1) << 8); + static const widelimb two64m8 = (((widelimb)1) << 64) - (((widelimb)1) << 8); + static const widelimb two64m48m8 = + (((widelimb)1) << 64) - (((widelimb)1) << 48) - (((widelimb)1) << 8); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two64p8; + out[1] += two64m48m8; + out[2] += two64m8; + out[3] += two64m8; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* Multiply a field element by a scalar: out = out * scalar + * The scalars we actually use are small, so results fit without overflow */ +static void felem_scalar(felem out, const limb scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} + +/* Multiply an unreduced field element by a scalar: out = out * scalar + * The scalars we actually use are small, so results fit without overflow */ +static void widefelem_scalar(widefelem out, const widelimb scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; +} + +/* Square a field element: out = in^2 */ +static void felem_square(widefelem out, const felem in) { + limb tmp0, tmp1, tmp2; + tmp0 = 2 * in[0]; + tmp1 = 2 * in[1]; + tmp2 = 2 * in[2]; + out[0] = ((widelimb)in[0]) * in[0]; + out[1] = ((widelimb)in[0]) * tmp1; + out[2] = ((widelimb)in[0]) * tmp2 + ((widelimb)in[1]) * in[1]; + out[3] = ((widelimb)in[3]) * tmp0 + ((widelimb)in[1]) * tmp2; + out[4] = ((widelimb)in[3]) * tmp1 + ((widelimb)in[2]) * in[2]; + out[5] = ((widelimb)in[3]) * tmp2; + out[6] = ((widelimb)in[3]) * in[3]; +} + +/* Multiply two field elements: out = in1 * in2 */ +static void felem_mul(widefelem out, const felem in1, const felem in2) { + out[0] = ((widelimb)in1[0]) * in2[0]; + out[1] = ((widelimb)in1[0]) * in2[1] + ((widelimb)in1[1]) * in2[0]; + out[2] = ((widelimb)in1[0]) * in2[2] + ((widelimb)in1[1]) * in2[1] + + ((widelimb)in1[2]) * in2[0]; + out[3] = ((widelimb)in1[0]) * in2[3] + ((widelimb)in1[1]) * in2[2] + + ((widelimb)in1[2]) * in2[1] + ((widelimb)in1[3]) * in2[0]; + out[4] = ((widelimb)in1[1]) * in2[3] + ((widelimb)in1[2]) * in2[2] + + ((widelimb)in1[3]) * in2[1]; + out[5] = ((widelimb)in1[2]) * in2[3] + ((widelimb)in1[3]) * in2[2]; + out[6] = ((widelimb)in1[3]) * in2[3]; +} + +/* Reduce seven 128-bit coefficients to four 64-bit coefficients. + * Requires in[i] < 2^126, + * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 */ +static void felem_reduce(felem out, const widefelem in) { + static const widelimb two127p15 = + (((widelimb)1) << 127) + (((widelimb)1) << 15); + static const widelimb two127m71 = + (((widelimb)1) << 127) - (((widelimb)1) << 71); + static const widelimb two127m71m55 = + (((widelimb)1) << 127) - (((widelimb)1) << 71) - (((widelimb)1) << 55); + widelimb output[5]; + + /* Add 0 mod 2^224-2^96+1 to ensure all differences are positive */ + output[0] = in[0] + two127p15; + output[1] = in[1] + two127m71m55; + output[2] = in[2] + two127m71; + output[3] = in[3]; + output[4] = in[4]; + + /* Eliminate in[4], in[5], in[6] */ + output[4] += in[6] >> 16; + output[3] += (in[6] & 0xffff) << 40; + output[2] -= in[6]; + + output[3] += in[5] >> 16; + output[2] += (in[5] & 0xffff) << 40; + output[1] -= in[5]; + + output[2] += output[4] >> 16; + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 2 -> 3 -> 4 */ + output[3] += output[2] >> 56; + output[2] &= 0x00ffffffffffffff; + + output[4] = output[3] >> 56; + output[3] &= 0x00ffffffffffffff; + + /* Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72 */ + + /* Eliminate output[4] */ + output[2] += output[4] >> 16; + /* output[2] < 2^56 + 2^56 = 2^57 */ + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 0 -> 1 -> 2 -> 3 */ + output[1] += output[0] >> 56; + out[0] = output[0] & 0x00ffffffffffffff; + + output[2] += output[1] >> 56; + /* output[2] < 2^57 + 2^72 */ + out[1] = output[1] & 0x00ffffffffffffff; + output[3] += output[2] >> 56; + /* output[3] <= 2^56 + 2^16 */ + out[2] = output[2] & 0x00ffffffffffffff; + + /* out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, + * out[3] <= 2^56 + 2^16 (due to final carry), + * so out < 2*p */ + out[3] = output[3]; +} + +/* Reduce to unique minimal representation. + * Requires 0 <= in < 2*p (always call felem_reduce first) */ +static void felem_contract(felem out, const felem in) { + static const int64_t two56 = ((limb)1) << 56; + /* 0 <= in < 2*p, p = 2^224 - 2^96 + 1 */ + /* if in > p , reduce in = in - 2^224 + 2^96 - 1 */ + int64_t tmp[4], a; + tmp[0] = in[0]; + tmp[1] = in[1]; + tmp[2] = in[2]; + tmp[3] = in[3]; + /* Case 1: a = 1 iff in >= 2^224 */ + a = (in[3] >> 56); + tmp[0] -= a; + tmp[1] += a << 40; + tmp[3] &= 0x00ffffffffffffff; + /* Case 2: a = 0 iff p <= in < 2^224, i.e., the high 128 bits are all 1 and + * the lower part is non-zero */ + a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) | + (((int64_t)(in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63); + a &= 0x00ffffffffffffff; + /* turn a into an all-one mask (if a = 0) or an all-zero mask */ + a = (a - 1) >> 63; + /* subtract 2^224 - 2^96 + 1 if a is all-one */ + tmp[3] &= a ^ 0xffffffffffffffff; + tmp[2] &= a ^ 0xffffffffffffffff; + tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff; + tmp[0] -= 1 & a; + + /* eliminate negative coefficients: if tmp[0] is negative, tmp[1] must + * be non-zero, so we only need one step */ + a = tmp[0] >> 63; + tmp[0] += two56 & a; + tmp[1] -= 1 & a; + + /* carry 1 -> 2 -> 3 */ + tmp[2] += tmp[1] >> 56; + tmp[1] &= 0x00ffffffffffffff; + + tmp[3] += tmp[2] >> 56; + tmp[2] &= 0x00ffffffffffffff; + + /* Now 0 <= out < p */ + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} + +/* Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field + * elements are reduced to in < 2^225, so we only need to check three cases: 0, + * 2^224 - 2^96 + 1, and 2^225 - 2^97 + 2 */ +static limb felem_is_zero(const felem in) { + limb zero = in[0] | in[1] | in[2] | in[3]; + zero = (((int64_t)(zero)-1) >> 63) & 1; + + limb two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000) | + (in[2] ^ 0x00ffffffffffffff) | + (in[3] ^ 0x00ffffffffffffff); + two224m96p1 = (((int64_t)(two224m96p1)-1) >> 63) & 1; + limb two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000) | + (in[2] ^ 0x00ffffffffffffff) | + (in[3] ^ 0x01ffffffffffffff); + two225m97p2 = (((int64_t)(two225m97p2)-1) >> 63) & 1; + return (zero | two224m96p1 | two225m97p2); +} + +/* Invert a field element */ +/* Computation chain copied from djb's code */ +static void felem_inv(felem out, const felem in) { + felem ftmp, ftmp2, ftmp3, ftmp4; + widefelem tmp; + size_t i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^4 - 2 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^5 - 4 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^6 - 8 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^7 - 2 */ + for (i = 0; i < 5; ++i) { /* 2^12 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); /* 2^12 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^13 - 2 */ + for (i = 0; i < 11; ++i) {/* 2^24 - 2^12 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^24 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^25 - 2 */ + for (i = 0; i < 23; ++i) {/* 2^48 - 2^24 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^48 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^49 - 2 */ + for (i = 0; i < 47; ++i) {/* 2^96 - 2^48 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp3, ftmp4); + felem_reduce(ftmp3, tmp); /* 2^96 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^97 - 2 */ + for (i = 0; i < 23; ++i) {/* 2^120 - 2^24 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp2, ftmp4); + felem_reduce(ftmp2, tmp); /* 2^120 - 1 */ + for (i = 0; i < 6; ++i) { /* 2^126 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^126 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^127 - 2 */ + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^127 - 1 */ + for (i = 0; i < 97; ++i) {/* 2^224 - 2^97 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } + felem_mul(tmp, ftmp, ftmp3); + felem_reduce(out, tmp); /* 2^224 - 2^96 - 1 */ +} + +/* Copy in constant time: + * if icopy == 1, copy in to out, + * if icopy == 0, copy out to itself. */ +static void copy_conditional(felem out, const felem in, limb icopy) { + size_t i; + /* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */ + const limb copy = -icopy; + for (i = 0; i < 4; ++i) { + const limb tmp = copy & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/* ELLIPTIC CURVE POINT OPERATIONS + * + * Points are represented in Jacobian projective coordinates: + * (X, Y, Z) corresponds to the affine point (X/Z^2, Y/Z^3), + * or to the point at infinity if Z == 0. */ + +/* Double an elliptic curve point: + * (X', Y', Z') = 2 * (X, Y, Z), where + * X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2 + * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2 + * Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z + * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed, + * while x_out == y_in is not (maybe this works, but it's not tested). */ +static void point_double(felem x_out, felem y_out, felem z_out, + const felem x_in, const felem y_in, const felem z_in) { + widefelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + + felem_assign(ftmp, x_in); + felem_assign(ftmp2, x_in); + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + + /* beta = x*gamma */ + felem_mul(tmp, x_in, gamma); + felem_reduce(beta, tmp); + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^57 + 2^58 + 2 < 2^59 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^57 + 2^57 = 2^58 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^58 < 2^60 */ + felem_mul(tmp, ftmp, ftmp2); + /* tmp[i] < 2^60 * 2^59 * 4 = 2^121 */ + felem_reduce(alpha, tmp); + + /* x' = alpha^2 - 8*beta */ + felem_square(tmp, alpha); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^57 = 2^60 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(x_out, tmp); + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^57 + 2^57 = 2^58 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^57 + 2^57 = 2^58 */ + felem_square(tmp, ftmp); + /* tmp[i] < 4 * 2^58 * 2^58 = 2^118 */ + felem_diff_128_64(tmp, delta); + /* tmp[i] < 2^118 + 2^64 + 8 < 2^119 */ + felem_reduce(z_out, tmp); + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^57 = 2^59 */ + felem_diff(beta, x_out); + /* beta[i] < 2^59 + 2^58 + 2 < 2^60 */ + felem_mul(tmp, alpha, beta); + /* tmp[i] < 4 * 2^57 * 2^60 = 2^119 */ + felem_square(tmp2, gamma); + /* tmp2[i] < 4 * 2^57 * 2^57 = 2^116 */ + widefelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 2^116 = 2^119 */ + widefelem_diff(tmp, tmp2); + /* tmp[i] < 2^119 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp); +} + +/* Add two elliptic curve points: + * (X_1, Y_1, Z_1) + (X_2, Y_2, Z_2) = (X_3, Y_3, Z_3), where + * X_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1)^2 - (Z_1^2 * X_2 - Z_2^2 * X_1)^3 - + * 2 * Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2 + * Y_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1) * (Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * + * X_1)^2 - X_3) - + * Z_2^3 * Y_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^3 + * Z_3 = (Z_1^2 * X_2 - Z_2^2 * X_1) * (Z_1 * Z_2) + * + * This runs faster if 'mixed' is set, which requires Z_2 = 1 or Z_2 = 0. */ + +/* This function is not entirely constant-time: it includes a branch for + * checking whether the two input points are equal, (while not equal to the + * point at infinity). This case never happens during single point + * multiplication, so there is no timing leak for ECDH or ECDSA signing. */ +static void point_add(felem x3, felem y3, felem z3, const felem x1, + const felem y1, const felem z1, const int mixed, + const felem x2, const felem y2, const felem z2) { + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out; + widefelem tmp, tmp2; + limb z1_is_zero, z2_is_zero, x_equal, y_equal; + + if (!mixed) { + /* ftmp2 = z2^2 */ + felem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + + /* ftmp4 = z2^3 */ + felem_mul(tmp, ftmp2, z2); + felem_reduce(ftmp4, tmp); + + /* ftmp4 = z2^3*y1 */ + felem_mul(tmp2, ftmp4, y1); + felem_reduce(ftmp4, tmp2); + + /* ftmp2 = z2^2*x1 */ + felem_mul(tmp2, ftmp2, x1); + felem_reduce(ftmp2, tmp2); + } else { + /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */ + + /* ftmp4 = z2^3*y1 */ + felem_assign(ftmp4, y1); + + /* ftmp2 = z2^2*x1 */ + felem_assign(ftmp2, x1); + } + + /* ftmp = z1^2 */ + felem_square(tmp, z1); + felem_reduce(ftmp, tmp); + + /* ftmp3 = z1^3 */ + felem_mul(tmp, ftmp, z1); + felem_reduce(ftmp3, tmp); + + /* tmp = z1^3*y2 */ + felem_mul(tmp, ftmp3, y2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp3 = z1^3*y2 - z2^3*y1 */ + felem_diff_128_64(tmp, ftmp4); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp3, tmp); + + /* tmp = z1^2*x2 */ + felem_mul(tmp, ftmp, x2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp = z1^2*x2 - z2^2*x1 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp, tmp); + + /* the formulae are incorrect if the points are equal + * so we check for this and do doubling if this happens */ + x_equal = felem_is_zero(ftmp); + y_equal = felem_is_zero(ftmp3); + z1_is_zero = felem_is_zero(z1); + z2_is_zero = felem_is_zero(z2); + /* In affine coordinates, (X_1, Y_1) == (X_2, Y_2) */ + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* ftmp5 = z1*z2 */ + if (!mixed) { + felem_mul(tmp, z1, z2); + felem_reduce(ftmp5, tmp); + } else { + /* special case z2 = 0 is handled later */ + felem_assign(ftmp5, z1); + } + + /* z_out = (z1^2*x2 - z2^2*x1)*(z1*z2) */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(z_out, tmp); + + /* ftmp = (z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* ftmp5 = (z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(ftmp5, tmp); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); + + /* tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp4, ftmp5); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 */ + felem_square(tmp2, ftmp3); + /* tmp2[i] < 4 * 2^57 * 2^57 < 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^116 + 2^64 + 8 < 2^117 */ + + /* ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp2); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2 * 2^57 = 2^58 */ + + /* x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 - + 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^117 + 2^64 + 8 < 2^118 */ + felem_reduce(x_out, tmp2); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out */ + felem_diff(ftmp2, x_out); + /* ftmp2[i] < 2^57 + 2^58 + 2 < 2^59 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) */ + felem_mul(tmp2, ftmp3, ftmp2); + /* tmp2[i] < 4 * 2^57 * 2^59 = 2^118 */ + + /* y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) - + z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ + widefelem_diff(tmp2, tmp); + /* tmp2[i] < 2^118 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp2); + + /* the result (x_out, y_out, z_out) is incorrect if one of the inputs is + * the point at infinity, so we need to check for this separately */ + + /* if point 1 is at infinity, copy point 2 to output, and vice versa */ + copy_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* select_point selects the |idx|th point from a precomputation table and + * copies it to out. */ +static void select_point(const u64 idx, size_t size, + const felem pre_comp[/*size*/][3], felem out[3]) { + limb *outlimbs = &out[0][0]; + memset(outlimbs, 0, 3 * sizeof(felem)); + + size_t i; + for (i = 0; i < size; i++) { + const limb *inlimbs = &pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + size_t j; + for (j = 0; j < 4 * 3; j++) { + outlimbs[j] |= inlimbs[j] & mask; + } + } +} + +/* get_bit returns the |i|th bit in |in| */ +static char get_bit(const felem_bytearray in, size_t i) { + if (i >= 224) { + return 0; + } + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* Interleaved point multiplication using precomputed point multiples: + * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], + * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple + * of the generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const size_t num_points, const u8 *g_scalar, + const felem pre_comp[][17][3]) { + felem nq[3], tmp[4]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, 3 * sizeof(felem)); + + /* Loop over all scalars msb-to-lsb, interleaving additions + * of multiples of the generator (two in each of the last 28 rounds) + * and additions of other points multiples (every 5th round). */ + int skip = 1; /* save two point operations in the first round */ + size_t i = num_points != 0 ? 220 : 27; + for (;;) { + /* double */ + if (!skip) { + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + } + + /* add multiples of the generator */ + if (g_scalar != NULL && i <= 27) { + /* first, look 28 bits upwards */ + bits = get_bit(g_scalar, i + 196) << 3; + bits |= get_bit(g_scalar, i + 140) << 2; + bits |= get_bit(g_scalar, i + 84) << 1; + bits |= get_bit(g_scalar, i + 28); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 168) << 3; + bits |= get_bit(g_scalar, i + 112) << 2; + bits |= get_bit(g_scalar, i + 56) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0], + tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points != 0 && i % 5 == 0) { + /* loop over all scalars */ + size_t num; + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* select the point to add or subtract */ + select_point(digit, 17, pre_comp[num], tmp); + felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */ + copy_conditional(tmp[1], tmp[3], sign); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + } + + if (i == 0) { + break; + } + --i; + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} + +/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns + * (X', Y') = (X/Z^2, Y/Z^3) */ +static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { + felem z1, z2, x_in, y_in, x_out, y_out; + widefelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + + if (!BN_to_felem(x_in, &point->X) || + !BN_to_felem(y_in, &point->Y) || + !BN_to_felem(z1, &point->Z)) { + return 0; + } + + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL && !felem_to_BN(x, x_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL && !felem_to_BN(y, y_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + + return 1; +} + +static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, + EC_POINT *r, + const BIGNUM *g_scalar, + const EC_POINT *p_, + const BIGNUM *p_scalar_, + BN_CTX *ctx) { + /* TODO: This function used to take |points| and |scalars| as arrays of + * |num| elements. The code below should be simplified to work in terms of + * |p_| and |p_scalar_|. */ + size_t num = p_ != NULL ? 1 : 0; + const EC_POINT **points = p_ != NULL ? &p_ : NULL; + BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL; + + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + felem(*pre_comp)[17][3] = NULL; + felem_bytearray tmp; + size_t num_points = num; + felem x_in, y_in, z_in, x_out, y_out, z_out; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + if (ctx == NULL) { + ctx = BN_CTX_new(); + new_ctx = ctx; + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + if ((x = BN_CTX_get(ctx)) == NULL || + (y = BN_CTX_get(ctx)) == NULL || + (z = BN_CTX_get(ctx)) == NULL || + (tmp_scalar = BN_CTX_get(ctx)) == NULL) { + goto err; + } + + if (num_points > 0) { + secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); + pre_comp = OPENSSL_malloc(num_points * sizeof(felem[17][3])); + if (secrets == NULL || + pre_comp == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination */ + memset(secrets, 0, num_points * sizeof(felem_bytearray)); + memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem)); + size_t i; + for (i = 0; i < num_points; ++i) { + if (i == num) { + /* the generator */ + p = EC_GROUP_get0_generator(group); + p_scalar = g_scalar; + } else { + /* the i^th point */ + p = points[i]; + p_scalar = scalars[i]; + } + + if (p_scalar != NULL && p != NULL) { + size_t num_bytes; + /* reduce g_scalar to 0 <= g_scalar < 2^224 */ + if (BN_num_bits(p_scalar) > 224 || BN_is_negative(p_scalar)) { + /* this is an unusual input, and we don't guarantee + * constant-timeness */ + if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(p_scalar, tmp); + } + + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if (!BN_to_felem(x_out, &p->X) || + !BN_to_felem(y_out, &p->Y) || + !BN_to_felem(z_out, &p->Z)) { + goto err; + } + + felem_assign(pre_comp[i][1][0], x_out); + felem_assign(pre_comp[i][1][1], y_out); + felem_assign(pre_comp[i][1][2], z_out); + + size_t j; + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add(pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], + pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2], + 0, pre_comp[i][j - 1][0], pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], pre_comp[i][j / 2][2]); + } + } + } + } + } + + if (g_scalar != NULL) { + memset(g_secret, 0, sizeof(g_secret)); + size_t num_bytes; + /* reduce g_scalar to 0 <= g_scalar < 2^224 */ + if (BN_num_bits(g_scalar) > 224 || BN_is_negative(g_scalar)) { + /* this is an unusual input, and we don't guarantee constant-timeness */ + if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(g_scalar, tmp); + } + + flip_endian(g_secret, tmp, num_bytes); + } + batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets, + num_points, g_scalar != NULL ? g_secret : NULL, + (const felem(*)[17][3])pre_comp); + + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if (!felem_to_BN(x, x_in) || + !felem_to_BN(y, y_in) || + !felem_to_BN(z, z_in)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + return ret; +} + +const EC_METHOD *EC_GFp_nistp224_method(void) { + static const EC_METHOD ret = {ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_copy, + ec_GFp_simple_group_set_curve, + ec_GFp_nistp224_point_get_affine_coordinates, + ec_GFp_nistp224_points_mul, + 0 /* check_pub_key_order */, + ec_GFp_simple_field_mul, + ec_GFp_simple_field_sqr, + 0 /* field_encode */, + 0 /* field_decode */}; + + return &ret; +} + +#endif /* 64_BIT && !WINDOWS && !SMALL */ diff --git a/external/boringssl/crypto/ec/p256-64.c b/external/boringssl/crypto/ec/p256-64.c new file mode 100644 index 0000000000..c4259b629f --- /dev/null +++ b/external/boringssl/crypto/ec/p256-64.c @@ -0,0 +1,1753 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* A 64-bit implementation of the NIST P-256 elliptic curve point + * multiplication + * + * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. + * Otherwise based on Emilia's P224 work, which was inspired by my curve25519 + * work which got its smarts from Daniel J. Bernstein's work on the same. */ + +#include + +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) + +#include +#include +#include +#include + +#include + +#include "internal.h" +#include "../internal.h" + + +typedef uint8_t u8; +typedef uint64_t u64; +typedef int64_t s64; + +/* The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We + * can serialise an element of this field into 32 bytes. We call this an + * felem_bytearray. */ +typedef u8 felem_bytearray[32]; + +/* The representation of field elements. + * ------------------------------------ + * + * We represent field elements with either four 128-bit values, eight 128-bit + * values, or four 64-bit values. The field element represented is: + * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p) + * or: + * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p) + * + * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits + * apart, but are 128-bits wide, the most significant bits of each limb overlap + * with the least significant bits of the next. + * + * A field element with four limbs is an 'felem'. One with eight limbs is a + * 'longfelem' + * + * A field element with four, 64-bit values is called a 'smallfelem'. Small + * values are used as intermediate values before multiplication. */ + +#define NLIMBS 4 + +typedef uint128_t limb; +typedef limb felem[NLIMBS]; +typedef limb longfelem[NLIMBS * 2]; +typedef u64 smallfelem[NLIMBS]; + +/* This is the value of the prime as four 64-bit words, little-endian. */ +static const u64 kPrime[4] = {0xfffffffffffffffful, 0xffffffff, 0, + 0xffffffff00000001ul}; +static const u64 bottom63bits = 0x7ffffffffffffffful; + +/* bin32_to_felem takes a little-endian byte array and converts it into felem + * form. This assumes that the CPU is little-endian. */ +static void bin32_to_felem(felem out, const u8 in[32]) { + out[0] = *((const u64 *)&in[0]); + out[1] = *((const u64 *)&in[8]); + out[2] = *((const u64 *)&in[16]); + out[3] = *((const u64 *)&in[24]); +} + +/* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian, + * 32 byte array. This assumes that the CPU is little-endian. */ +static void smallfelem_to_bin32(u8 out[32], const smallfelem in) { + *((u64 *)&out[0]) = in[0]; + *((u64 *)&out[8]) = in[1]; + *((u64 *)&out[16]) = in[2]; + *((u64 *)&out[24]) = in[3]; +} + +/* To preserve endianness when using BN_bn2bin and BN_bin2bn. */ +static void flip_endian(u8 *out, const u8 *in, size_t len) { + size_t i; + for (i = 0; i < len; ++i) { + out[i] = in[len - 1 - i]; + } +} + +/* BN_to_felem converts an OpenSSL BIGNUM into an felem. */ +static int BN_to_felem(felem out, const BIGNUM *bn) { + if (BN_is_negative(bn)) { + OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + + felem_bytearray b_out; + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof(b_out)); + size_t num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof(b_out)) { + OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + + felem_bytearray b_in; + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin32_to_felem(out, b_out); + return 1; +} + +/* felem_to_BN converts an felem into an OpenSSL BIGNUM. */ +static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) { + felem_bytearray b_in, b_out; + smallfelem_to_bin32(b_in, in); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); +} + +/* Field operations. */ + +static void felem_assign(felem out, const felem in) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* felem_sum sets out = out + in. */ +static void felem_sum(felem out, const felem in) { + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* felem_small_sum sets out = out + in. */ +static void felem_small_sum(felem out, const smallfelem in) { + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* felem_scalar sets out = out * scalar */ +static void felem_scalar(felem out, const u64 scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} + +/* longfelem_scalar sets out = out * scalar */ +static void longfelem_scalar(longfelem out, const u64 scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; +} + +#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9) +#define two105 (((limb)1) << 105) +#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9) + +/* zero105 is 0 mod p */ +static const felem zero105 = {two105m41m9, two105, two105m41p9, two105m41p9}; + +/* smallfelem_neg sets |out| to |-small| + * On exit: + * out[i] < out[i] + 2^105 */ +static void smallfelem_neg(felem out, const smallfelem small) { + /* In order to prevent underflow, we subtract from 0 mod p. */ + out[0] = zero105[0] - small[0]; + out[1] = zero105[1] - small[1]; + out[2] = zero105[2] - small[2]; + out[3] = zero105[3] - small[3]; +} + +/* felem_diff subtracts |in| from |out| + * On entry: + * in[i] < 2^104 + * On exit: + * out[i] < out[i] + 2^105. */ +static void felem_diff(felem out, const felem in) { + /* In order to prevent underflow, we add 0 mod p before subtracting. */ + out[0] += zero105[0]; + out[1] += zero105[1]; + out[2] += zero105[2]; + out[3] += zero105[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11) +#define two107 (((limb)1) << 107) +#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) + +/* zero107 is 0 mod p */ +static const felem zero107 = {two107m43m11, two107, two107m43p11, two107m43p11}; + +/* An alternative felem_diff for larger inputs |in| + * felem_diff_zero107 subtracts |in| from |out| + * On entry: + * in[i] < 2^106 + * On exit: + * out[i] < out[i] + 2^107. */ +static void felem_diff_zero107(felem out, const felem in) { + /* In order to prevent underflow, we add 0 mod p before subtracting. */ + out[0] += zero107[0]; + out[1] += zero107[1]; + out[2] += zero107[2]; + out[3] += zero107[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* longfelem_diff subtracts |in| from |out| + * On entry: + * in[i] < 7*2^67 + * On exit: + * out[i] < out[i] + 2^70 + 2^40. */ +static void longfelem_diff(longfelem out, const longfelem in) { + static const limb two70m8p6 = + (((limb)1) << 70) - (((limb)1) << 8) + (((limb)1) << 6); + static const limb two70p40 = (((limb)1) << 70) + (((limb)1) << 40); + static const limb two70 = (((limb)1) << 70); + static const limb two70m40m38p6 = (((limb)1) << 70) - (((limb)1) << 40) - + (((limb)1) << 38) + (((limb)1) << 6); + static const limb two70m6 = (((limb)1) << 70) - (((limb)1) << 6); + + /* add 0 mod p to avoid underflow */ + out[0] += two70m8p6; + out[1] += two70p40; + out[2] += two70; + out[3] += two70m40m38p6; + out[4] += two70m6; + out[5] += two70m6; + out[6] += two70m6; + out[7] += two70m6; + + /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */ + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; + out[7] -= in[7]; +} + +#define two64m0 (((limb)1) << 64) - 1 +#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1 +#define two64m46 (((limb)1) << 64) - (((limb)1) << 46) +#define two64m32 (((limb)1) << 64) - (((limb)1) << 32) + +/* zero110 is 0 mod p. */ +static const felem zero110 = {two64m0, two110p32m0, two64m46, two64m32}; + +/* felem_shrink converts an felem into a smallfelem. The result isn't quite + * minimal as the value may be greater than p. + * + * On entry: + * in[i] < 2^109 + * On exit: + * out[i] < 2^64. */ +static void felem_shrink(smallfelem out, const felem in) { + felem tmp; + u64 a, b, mask; + s64 high, low; + static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */ + + /* Carry 2->3 */ + tmp[3] = zero110[3] + in[3] + ((u64)(in[2] >> 64)); + /* tmp[3] < 2^110 */ + + tmp[2] = zero110[2] + (u64)in[2]; + tmp[0] = zero110[0] + in[0]; + tmp[1] = zero110[1] + in[1]; + /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */ + + /* We perform two partial reductions where we eliminate the high-word of + * tmp[3]. We don't update the other words till the end. */ + a = tmp[3] >> 64; /* a < 2^46 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb)a) << 32; + /* tmp[3] < 2^79 */ + + b = a; + a = tmp[3] >> 64; /* a < 2^15 */ + b += a; /* b < 2^46 + 2^15 < 2^47 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb)a) << 32; + /* tmp[3] < 2^64 + 2^47 */ + + /* This adjusts the other two words to complete the two partial + * reductions. */ + tmp[0] += b; + tmp[1] -= (((limb)b) << 32); + + /* In order to make space in tmp[3] for the carry from 2 -> 3, we + * conditionally subtract kPrime if tmp[3] is large enough. */ + high = tmp[3] >> 64; + /* As tmp[3] < 2^65, high is either 1 or 0 */ + high = ~(high - 1); + /* high is: + * all ones if the high word of tmp[3] is 1 + * all zeros if the high word of tmp[3] if 0 */ + low = tmp[3]; + mask = low >> 63; + /* mask is: + * all ones if the MSB of low is 1 + * all zeros if the MSB of low if 0 */ + low &= bottom63bits; + low -= kPrime3Test; + /* if low was greater than kPrime3Test then the MSB is zero */ + low = ~low; + low >>= 63; + /* low is: + * all ones if low was > kPrime3Test + * all zeros if low was <= kPrime3Test */ + mask = (mask & low) | high; + tmp[0] -= mask & kPrime[0]; + tmp[1] -= mask & kPrime[1]; + /* kPrime[2] is zero, so omitted */ + tmp[3] -= mask & kPrime[3]; + /* tmp[3] < 2**64 - 2**32 + 1 */ + + tmp[1] += ((u64)(tmp[0] >> 64)); + tmp[0] = (u64)tmp[0]; + tmp[2] += ((u64)(tmp[1] >> 64)); + tmp[1] = (u64)tmp[1]; + tmp[3] += ((u64)(tmp[2] >> 64)); + tmp[2] = (u64)tmp[2]; + /* tmp[i] < 2^64 */ + + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} + +/* smallfelem_expand converts a smallfelem to an felem */ +static void smallfelem_expand(felem out, const smallfelem in) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* smallfelem_square sets |out| = |small|^2 + * On entry: + * small[i] < 2^64 + * On exit: + * out[i] < 7 * 2^64 < 2^67 */ +static void smallfelem_square(longfelem out, const smallfelem small) { + limb a; + u64 high, low; + + a = ((uint128_t)small[0]) * small[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t)small[0]) * small[1]; + low = a; + high = a >> 64; + out[1] += low; + out[1] += low; + out[2] = high; + + a = ((uint128_t)small[0]) * small[2]; + low = a; + high = a >> 64; + out[2] += low; + out[2] *= 2; + out[3] = high; + + a = ((uint128_t)small[0]) * small[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t)small[1]) * small[2]; + low = a; + high = a >> 64; + out[3] += low; + out[3] *= 2; + out[4] += high; + + a = ((uint128_t)small[1]) * small[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t)small[1]) * small[3]; + low = a; + high = a >> 64; + out[4] += low; + out[4] *= 2; + out[5] = high; + + a = ((uint128_t)small[2]) * small[3]; + low = a; + high = a >> 64; + out[5] += low; + out[5] *= 2; + out[6] = high; + out[6] += high; + + a = ((uint128_t)small[2]) * small[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t)small[3]) * small[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/*felem_square sets |out| = |in|^2 + * On entry: + * in[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67. */ +static void felem_square(longfelem out, const felem in) { + u64 small[4]; + felem_shrink(small, in); + smallfelem_square(out, small); +} + +/* smallfelem_mul sets |out| = |small1| * |small2| + * On entry: + * small1[i] < 2^64 + * small2[i] < 2^64 + * On exit: + * out[i] < 7 * 2^64 < 2^67. */ +static void smallfelem_mul(longfelem out, const smallfelem small1, + const smallfelem small2) { + limb a; + u64 high, low; + + a = ((uint128_t)small1[0]) * small2[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t)small1[0]) * small2[1]; + low = a; + high = a >> 64; + out[1] += low; + out[2] = high; + + a = ((uint128_t)small1[1]) * small2[0]; + low = a; + high = a >> 64; + out[1] += low; + out[2] += high; + + a = ((uint128_t)small1[0]) * small2[2]; + low = a; + high = a >> 64; + out[2] += low; + out[3] = high; + + a = ((uint128_t)small1[1]) * small2[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t)small1[2]) * small2[0]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t)small1[0]) * small2[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t)small1[1]) * small2[2]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t)small1[2]) * small2[1]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t)small1[3]) * small2[0]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t)small1[1]) * small2[3]; + low = a; + high = a >> 64; + out[4] += low; + out[5] = high; + + a = ((uint128_t)small1[2]) * small2[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t)small1[3]) * small2[1]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t)small1[2]) * small2[3]; + low = a; + high = a >> 64; + out[5] += low; + out[6] = high; + + a = ((uint128_t)small1[3]) * small2[2]; + low = a; + high = a >> 64; + out[5] += low; + out[6] += high; + + a = ((uint128_t)small1[3]) * small2[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/* felem_mul sets |out| = |in1| * |in2| + * On entry: + * in1[i] < 2^109 + * in2[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67 */ +static void felem_mul(longfelem out, const felem in1, const felem in2) { + smallfelem small1, small2; + felem_shrink(small1, in1); + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +/* felem_small_mul sets |out| = |small1| * |in2| + * On entry: + * small1[i] < 2^64 + * in2[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67 */ +static void felem_small_mul(longfelem out, const smallfelem small1, + const felem in2) { + smallfelem small2; + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4) +#define two100 (((limb)1) << 100) +#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4) + +/* zero100 is 0 mod p */ +static const felem zero100 = {two100m36m4, two100, two100m36p4, two100m36p4}; + +/* Internal function for the different flavours of felem_reduce. + * felem_reduce_ reduces the higher coefficients in[4]-in[7]. + * On entry: + * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7] + * out[1] >= in[7] + 2^32*in[4] + * out[2] >= in[5] + 2^32*in[5] + * out[3] >= in[4] + 2^32*in[5] + 2^32*in[6] + * On exit: + * out[0] <= out[0] + in[4] + 2^32*in[5] + * out[1] <= out[1] + in[5] + 2^33*in[6] + * out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7] + * out[3] <= out[3] + 2^32*in[4] + 3*in[7] */ +static void felem_reduce_(felem out, const longfelem in) { + int128_t c; + /* combine common terms from below */ + c = in[4] + (in[5] << 32); + out[0] += c; + out[3] -= c; + + c = in[5] - in[7]; + out[1] += c; + out[2] -= c; + + /* the remaining terms */ + /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */ + out[1] -= (in[4] << 32); + out[3] += (in[4] << 32); + + /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */ + out[2] -= (in[5] << 32); + + /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */ + out[0] -= in[6]; + out[0] -= (in[6] << 32); + out[1] += (in[6] << 33); + out[2] += (in[6] * 2); + out[3] -= (in[6] << 32); + + /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */ + out[0] -= in[7]; + out[0] -= (in[7] << 32); + out[2] += (in[7] << 33); + out[3] += (in[7] * 3); +} + +/* felem_reduce converts a longfelem into an felem. + * To be called directly after felem_square or felem_mul. + * On entry: + * in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64 + * in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64 + * On exit: + * out[i] < 2^101 */ +static void felem_reduce(felem out, const longfelem in) { + out[0] = zero100[0] + in[0]; + out[1] = zero100[1] + in[1]; + out[2] = zero100[2] + in[2]; + out[3] = zero100[3] + in[3]; + + felem_reduce_(out, in); + + /* out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0 + * out[1] > 2^100 - 2^64 - 7*2^96 > 0 + * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0 + * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0 + * + * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101 + * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101 + * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101 + * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101 */ +} + +/* felem_reduce_zero105 converts a larger longfelem into an felem. + * On entry: + * in[0] < 2^71 + * On exit: + * out[i] < 2^106 */ +static void felem_reduce_zero105(felem out, const longfelem in) { + out[0] = zero105[0] + in[0]; + out[1] = zero105[1] + in[1]; + out[2] = zero105[2] + in[2]; + out[3] = zero105[3] + in[3]; + + felem_reduce_(out, in); + + /* out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0 + * out[1] > 2^105 - 2^71 - 2^103 > 0 + * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0 + * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0 + * + * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106 + * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106 */ +} + +/* subtract_u64 sets *result = *result - v and *carry to one if the + * subtraction underflowed. */ +static void subtract_u64(u64 *result, u64 *carry, u64 v) { + uint128_t r = *result; + r -= v; + *carry = (r >> 64) & 1; + *result = (u64)r; +} + +/* felem_contract converts |in| to its unique, minimal representation. On + * entry: in[i] < 2^109. */ +static void felem_contract(smallfelem out, const felem in) { + u64 all_equal_so_far = 0, result = 0; + + felem_shrink(out, in); + /* small is minimal except that the value might be > p */ + + all_equal_so_far--; + /* We are doing a constant time test if out >= kPrime. We need to compare + * each u64, from most-significant to least significant. For each one, if + * all words so far have been equal (m is all ones) then a non-equal + * result is the answer. Otherwise we continue. */ + size_t i; + for (i = 3; i < 4; i--) { + u64 equal; + uint128_t a = ((uint128_t)kPrime[i]) - out[i]; + /* if out[i] > kPrime[i] then a will underflow and the high 64-bits + * will all be set. */ + result |= all_equal_so_far & ((u64)(a >> 64)); + + /* if kPrime[i] == out[i] then |equal| will be all zeros and the + * decrement will make it all ones. */ + equal = kPrime[i] ^ out[i]; + equal--; + equal &= equal << 32; + equal &= equal << 16; + equal &= equal << 8; + equal &= equal << 4; + equal &= equal << 2; + equal &= equal << 1; + equal = ((s64)equal) >> 63; + + all_equal_so_far &= equal; + } + + /* if all_equal_so_far is still all ones then the two values are equal + * and so out >= kPrime is true. */ + result |= all_equal_so_far; + + /* if out >= kPrime then we subtract kPrime. */ + u64 carry; + subtract_u64(&out[0], &carry, result & kPrime[0]); + subtract_u64(&out[1], &carry, carry); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[1], &carry, result & kPrime[1]); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[2], &carry, result & kPrime[2]); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[3], &carry, result & kPrime[3]); +} + +/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 + * otherwise. + * On entry: + * small[i] < 2^64 */ +static limb smallfelem_is_zero(const smallfelem small) { + limb result; + u64 is_p; + + u64 is_zero = small[0] | small[1] | small[2] | small[3]; + is_zero--; + is_zero &= is_zero << 32; + is_zero &= is_zero << 16; + is_zero &= is_zero << 8; + is_zero &= is_zero << 4; + is_zero &= is_zero << 2; + is_zero &= is_zero << 1; + is_zero = ((s64)is_zero) >> 63; + + is_p = (small[0] ^ kPrime[0]) | (small[1] ^ kPrime[1]) | + (small[2] ^ kPrime[2]) | (small[3] ^ kPrime[3]); + is_p--; + is_p &= is_p << 32; + is_p &= is_p << 16; + is_p &= is_p << 8; + is_p &= is_p << 4; + is_p &= is_p << 2; + is_p &= is_p << 1; + is_p = ((s64)is_p) >> 63; + + is_zero |= is_p; + + result = is_zero; + result |= ((limb)is_zero) << 64; + return result; +} + +/* felem_inv calculates |out| = |in|^{-1} + * + * Based on Fermat's Little Theorem: + * a^p = a (mod p) + * a^{p-1} = 1 (mod p) + * a^{p-2} = a^{-1} (mod p) */ +static void felem_inv(felem out, const felem in) { + felem ftmp, ftmp2; + /* each e_I will hold |in|^{2^I - 1} */ + felem e2, e4, e8, e16, e32, e64; + longfelem tmp; + size_t i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ + felem_assign(e2, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */ + felem_mul(tmp, ftmp, e2); + felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */ + felem_assign(e4, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */ + felem_mul(tmp, ftmp, e4); + felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */ + felem_assign(e8, ftmp); + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^16 - 2^8 */ + felem_mul(tmp, ftmp, e8); + felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */ + felem_assign(e16, ftmp); + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^32 - 2^16 */ + felem_mul(tmp, ftmp, e16); + felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */ + felem_assign(e32, ftmp); + for (i = 0; i < 32; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^64 - 2^32 */ + felem_assign(e64, ftmp); + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */ + for (i = 0; i < 192; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^256 - 2^224 + 2^192 */ + + felem_mul(tmp, e64, e32); + felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */ + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^80 - 2^16 */ + felem_mul(tmp, ftmp2, e16); + felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */ + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^88 - 2^8 */ + felem_mul(tmp, ftmp2, e8); + felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */ + for (i = 0; i < 4; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^92 - 2^4 */ + felem_mul(tmp, ftmp2, e4); + felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */ + felem_mul(tmp, ftmp2, e2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */ + felem_mul(tmp, ftmp2, in); + felem_reduce(ftmp2, tmp); /* 2^96 - 3 */ + + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ +} + +/* Group operations + * ---------------- + * + * Building on top of the field operations we have the operations on the + * elliptic curve group itself. Points on the curve are represented in Jacobian + * coordinates. */ + +/* point_double calculates 2*(x_in, y_in, z_in) + * + * The method is taken from: + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + * + * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. + * while x_out == y_in is not (maybe this works, but it's not tested). */ +static void point_double(felem x_out, felem y_out, felem z_out, + const felem x_in, const felem y_in, const felem z_in) { + longfelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + smallfelem small1, small2; + + felem_assign(ftmp, x_in); + /* ftmp[i] < 2^106 */ + felem_assign(ftmp2, x_in); + /* ftmp2[i] < 2^106 */ + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + /* delta[i] < 2^101 */ + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + /* gamma[i] < 2^101 */ + felem_shrink(small1, gamma); + + /* beta = x*gamma */ + felem_small_mul(tmp, small1, x_in); + felem_reduce(beta, tmp); + /* beta[i] < 2^101 */ + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^105 + 2^106 < 2^107 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^105 + 2^106 < 2^107 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^107 < 2^109 */ + felem_mul(tmp, ftmp, ftmp2); + felem_reduce(alpha, tmp); + /* alpha[i] < 2^101 */ + felem_shrink(small2, alpha); + + /* x' = alpha^2 - 8*beta */ + smallfelem_square(tmp, small2); + felem_reduce(x_out, tmp); + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^101 = 2^104 */ + felem_diff(x_out, ftmp); + /* x_out[i] < 2^105 + 2^101 < 2^106 */ + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^101 + 2^101 = 2^102 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^106 + 2^106 = 2^107 */ + felem_square(tmp, ftmp); + felem_reduce(z_out, tmp); + felem_diff(z_out, delta); + /* z_out[i] < 2^105 + 2^101 < 2^106 */ + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^101 = 2^103 */ + felem_diff_zero107(beta, x_out); + /* beta[i] < 2^107 + 2^103 < 2^108 */ + felem_small_mul(tmp, small2, beta); + /* tmp[i] < 7 * 2^64 < 2^67 */ + smallfelem_square(tmp2, small1); + /* tmp2[i] < 7 * 2^64 */ + longfelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ +} + +/* point_double_small is the same as point_double, except that it operates on + * smallfelems. */ +static void point_double_small(smallfelem x_out, smallfelem y_out, + smallfelem z_out, const smallfelem x_in, + const smallfelem y_in, const smallfelem z_in) { + felem felem_x_out, felem_y_out, felem_z_out; + felem felem_x_in, felem_y_in, felem_z_in; + + smallfelem_expand(felem_x_in, x_in); + smallfelem_expand(felem_y_in, y_in); + smallfelem_expand(felem_z_in, z_in); + point_double(felem_x_out, felem_y_out, felem_z_out, felem_x_in, felem_y_in, + felem_z_in); + felem_shrink(x_out, felem_x_out); + felem_shrink(y_out, felem_y_out); + felem_shrink(z_out, felem_z_out); +} + +/* copy_conditional copies in to out iff mask is all ones. */ +static void copy_conditional(felem out, const felem in, limb mask) { + size_t i; + for (i = 0; i < NLIMBS; ++i) { + const limb tmp = mask & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/* copy_small_conditional copies in to out iff mask is all ones. */ +static void copy_small_conditional(felem out, const smallfelem in, limb mask) { + size_t i; + const u64 mask64 = mask; + for (i = 0; i < NLIMBS; ++i) { + out[i] = ((limb)(in[i] & mask64)) | (out[i] & ~mask); + } +} + +/* point_add calcuates (x1, y1, z1) + (x2, y2, z2) + * + * The method is taken from: + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, + * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). + * + * This function includes a branch for checking whether the two input points + * are equal, (while not equal to the point at infinity). This case never + * happens during single point multiplication, so there is no timing leak for + * ECDH or ECDSA signing. */ +static void point_add(felem x3, felem y3, felem z3, const felem x1, + const felem y1, const felem z1, const int mixed, + const smallfelem x2, const smallfelem y2, + const smallfelem z2) { + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; + longfelem tmp, tmp2; + smallfelem small1, small2, small3, small4, small5; + limb x_equal, y_equal, z1_is_zero, z2_is_zero; + + felem_shrink(small3, z1); + + z1_is_zero = smallfelem_is_zero(small3); + z2_is_zero = smallfelem_is_zero(z2); + + /* ftmp = z1z1 = z1**2 */ + smallfelem_square(tmp, small3); + felem_reduce(ftmp, tmp); + /* ftmp[i] < 2^101 */ + felem_shrink(small1, ftmp); + + if (!mixed) { + /* ftmp2 = z2z2 = z2**2 */ + smallfelem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + /* ftmp2[i] < 2^101 */ + felem_shrink(small2, ftmp2); + + felem_shrink(small5, x1); + + /* u1 = ftmp3 = x1*z2z2 */ + smallfelem_mul(tmp, small5, small2); + felem_reduce(ftmp3, tmp); + /* ftmp3[i] < 2^101 */ + + /* ftmp5 = z1 + z2 */ + felem_assign(ftmp5, z1); + felem_small_sum(ftmp5, z2); + /* ftmp5[i] < 2^107 */ + + /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */ + felem_square(tmp, ftmp5); + felem_reduce(ftmp5, tmp); + /* ftmp2 = z2z2 + z1z1 */ + felem_sum(ftmp2, ftmp); + /* ftmp2[i] < 2^101 + 2^101 = 2^102 */ + felem_diff(ftmp5, ftmp2); + /* ftmp5[i] < 2^105 + 2^101 < 2^106 */ + + /* ftmp2 = z2 * z2z2 */ + smallfelem_mul(tmp, small2, z2); + felem_reduce(ftmp2, tmp); + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_mul(tmp, y1, ftmp2); + felem_reduce(ftmp6, tmp); + /* ftmp6[i] < 2^101 */ + } else { + /* We'll assume z2 = 1 (special case z2 = 0 is handled later). */ + + /* u1 = ftmp3 = x1*z2z2 */ + felem_assign(ftmp3, x1); + /* ftmp3[i] < 2^106 */ + + /* ftmp5 = 2z1z2 */ + felem_assign(ftmp5, z1); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2*2^106 = 2^107 */ + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_assign(ftmp6, y1); + /* ftmp6[i] < 2^106 */ + } + + /* u2 = x2*z1z1 */ + smallfelem_mul(tmp, x2, small1); + felem_reduce(ftmp4, tmp); + + /* h = ftmp4 = u2 - u1 */ + felem_diff_zero107(ftmp4, ftmp3); + /* ftmp4[i] < 2^107 + 2^101 < 2^108 */ + felem_shrink(small4, ftmp4); + + x_equal = smallfelem_is_zero(small4); + + /* z_out = ftmp5 * h */ + felem_small_mul(tmp, small4, ftmp5); + felem_reduce(z_out, tmp); + /* z_out[i] < 2^101 */ + + /* ftmp = z1 * z1z1 */ + smallfelem_mul(tmp, small1, small3); + felem_reduce(ftmp, tmp); + + /* s2 = tmp = y2 * z1**3 */ + felem_small_mul(tmp, y2, ftmp); + felem_reduce(ftmp5, tmp); + + /* r = ftmp5 = (s2 - s1)*2 */ + felem_diff_zero107(ftmp5, ftmp6); + /* ftmp5[i] < 2^107 + 2^107 = 2^108 */ + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2^109 */ + felem_shrink(small1, ftmp5); + y_equal = smallfelem_is_zero(small1); + + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* I = ftmp = (2h)**2 */ + felem_assign(ftmp, ftmp4); + felem_scalar(ftmp, 2); + /* ftmp[i] < 2*2^108 = 2^109 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* J = ftmp2 = h * I */ + felem_mul(tmp, ftmp4, ftmp); + felem_reduce(ftmp2, tmp); + + /* V = ftmp4 = U1 * I */ + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); + + /* x_out = r**2 - J - 2V */ + smallfelem_square(tmp, small1); + felem_reduce(x_out, tmp); + felem_assign(ftmp3, ftmp4); + felem_scalar(ftmp4, 2); + felem_sum(ftmp4, ftmp2); + /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */ + felem_diff(x_out, ftmp4); + /* x_out[i] < 2^105 + 2^101 */ + + /* y_out = r(V-x_out) - 2 * s1 * J */ + felem_diff_zero107(ftmp3, x_out); + /* ftmp3[i] < 2^107 + 2^101 < 2^108 */ + felem_small_mul(tmp, small1, ftmp3); + felem_mul(tmp2, ftmp6, ftmp2); + longfelem_scalar(tmp2, 2); + /* tmp2[i] < 2*2^67 = 2^68 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ + + copy_small_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_small_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_small_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* point_add_small is the same as point_add, except that it operates on + * smallfelems. */ +static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3, + smallfelem x1, smallfelem y1, smallfelem z1, + smallfelem x2, smallfelem y2, smallfelem z2) { + felem felem_x3, felem_y3, felem_z3; + felem felem_x1, felem_y1, felem_z1; + smallfelem_expand(felem_x1, x1); + smallfelem_expand(felem_y1, y1); + smallfelem_expand(felem_z1, z1); + point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, x2, + y2, z2); + felem_shrink(x3, felem_x3); + felem_shrink(y3, felem_y3); + felem_shrink(z3, felem_z3); +} + +/* Base point pre computation + * -------------------------- + * + * Two different sorts of precomputed tables are used in the following code. + * Each contain various points on the curve, where each point is three field + * elements (x, y, z). + * + * For the base point table, z is usually 1 (0 for the point at infinity). + * This table has 2 * 16 elements, starting with the following: + * index | bits | point + * ------+---------+------------------------------ + * 0 | 0 0 0 0 | 0G + * 1 | 0 0 0 1 | 1G + * 2 | 0 0 1 0 | 2^64G + * 3 | 0 0 1 1 | (2^64 + 1)G + * 4 | 0 1 0 0 | 2^128G + * 5 | 0 1 0 1 | (2^128 + 1)G + * 6 | 0 1 1 0 | (2^128 + 2^64)G + * 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G + * 8 | 1 0 0 0 | 2^192G + * 9 | 1 0 0 1 | (2^192 + 1)G + * 10 | 1 0 1 0 | (2^192 + 2^64)G + * 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G + * 12 | 1 1 0 0 | (2^192 + 2^128)G + * 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G + * 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G + * 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G + * followed by a copy of this with each element multiplied by 2^32. + * + * The reason for this is so that we can clock bits into four different + * locations when doing simple scalar multiplies against the base point, + * and then another four locations using the second 16 elements. + * + * Tables for other points have table[i] = iG for i in 0 .. 16. */ + +/* g_pre_comp is the table of precomputed base points */ +static const smallfelem g_pre_comp[2][16][3] = { + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, + 0x6b17d1f2e12c4247}, + {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, + 0x4fe342e2fe1a7f9b}, + {1, 0, 0, 0}}, + {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, + 0x0fa822bc2811aaa5}, + {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, + 0xbff44ae8f5dba80d}, + {1, 0, 0, 0}}, + {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, + 0x300a4bbc89d6726f}, + {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, + 0x72aac7e0d09b4644}, + {1, 0, 0, 0}}, + {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, + 0x447d739beedb5e67}, + {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, + 0x2d4825ab834131ee}, + {1, 0, 0, 0}}, + {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, + 0xef9519328a9c72ff}, + {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, + 0x611e9fc37dbb2c9b}, + {1, 0, 0, 0}}, + {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, + 0x550663797b51f5d8}, + {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, + 0x157164848aecb851}, + {1, 0, 0, 0}}, + {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, + 0xeb5d7745b21141ea}, + {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, + 0xeafd72ebdbecc17b}, + {1, 0, 0, 0}}, + {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, + 0xa6d39677a7849276}, + {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, + 0x674f84749b0b8816}, + {1, 0, 0, 0}}, + {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, + 0x4e769e7672c9ddad}, + {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, + 0x42b99082de830663}, + {1, 0, 0, 0}}, + {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, + 0x78878ef61c6ce04d}, + {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, + 0xb6cb3f5d7b72c321}, + {1, 0, 0, 0}}, + {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, + 0x0c88bc4d716b1287}, + {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, + 0xdd5ddea3f3901dc6}, + {1, 0, 0, 0}}, + {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, + 0x68f344af6b317466}, + {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, + 0x31b9c405f8540a20}, + {1, 0, 0, 0}}, + {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, + 0x4052bf4b6f461db9}, + {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, + 0xfecf4d5190b0fc61}, + {1, 0, 0, 0}}, + {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, + 0x1eddbae2c802e41a}, + {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, + 0x43104d86560ebcfc}, + {1, 0, 0, 0}}, + {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, + 0xb48e26b484f7a21c}, + {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, + 0xfac015404d4d3dab}, + {1, 0, 0, 0}}}, + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, + 0x7fe36b40af22af89}, + {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, + 0xe697d45825b63624}, + {1, 0, 0, 0}}, + {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, + 0x4a5b506612a677a6}, + {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, + 0xeb13461ceac089f1}, + {1, 0, 0, 0}}, + {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, + 0x0781b8291c6a220a}, + {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, + 0x690cde8df0151593}, + {1, 0, 0, 0}}, + {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, + 0x8a535f566ec73617}, + {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, + 0x0455c08468b08bd7}, + {1, 0, 0, 0}}, + {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, + 0x06bada7ab77f8276}, + {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, + 0x5b476dfd0e6cb18a}, + {1, 0, 0, 0}}, + {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, + 0x3e29864e8a2ec908}, + {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, + 0x239b90ea3dc31e7e}, + {1, 0, 0, 0}}, + {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, + 0x820f4dd949f72ff7}, + {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, + 0x140406ec783a05ec}, + {1, 0, 0, 0}}, + {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, + 0x68f6b8542783dfee}, + {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, + 0xcbe1feba92e40ce6}, + {1, 0, 0, 0}}, + {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, + 0xd0b2f94d2f420109}, + {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, + 0x971459828b0719e5}, + {1, 0, 0, 0}}, + {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, + 0x961610004a866aba}, + {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, + 0x7acb9fadcee75e44}, + {1, 0, 0, 0}}, + {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, + 0x24eb9acca333bf5b}, + {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, + 0x69f891c5acd079cc}, + {1, 0, 0, 0}}, + {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, + 0xe51f547c5972a107}, + {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, + 0x1c309a2b25bb1387}, + {1, 0, 0, 0}}, + {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, + 0x20b87b8aa2c4e503}, + {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, + 0xf5c6fa49919776be}, + {1, 0, 0, 0}}, + {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, + 0x1ed7d1b9332010b9}, + {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, + 0x3a2b03f03217257a}, + {1, 0, 0, 0}}, + {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, + 0x15fee545c78dd9f6}, + {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, + 0x4ab5b6b2b8753f81}, + {1, 0, 0, 0}}}}; + +/* select_point selects the |idx|th point from a precomputation table and + * copies it to out. */ +static void select_point(const u64 idx, size_t size, + const smallfelem pre_comp[/*size*/][3], + smallfelem out[3]) { + u64 *outlimbs = &out[0][0]; + memset(outlimbs, 0, 3 * sizeof(smallfelem)); + + size_t i; + for (i = 0; i < size; i++) { + const u64 *inlimbs = (const u64 *)&pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + size_t j; + for (j = 0; j < NLIMBS * 3; j++) { + outlimbs[j] |= inlimbs[j] & mask; + } + } +} + +/* get_bit returns the |i|th bit in |in| */ +static char get_bit(const felem_bytearray in, int i) { + if (i < 0 || i >= 256) { + return 0; + } + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out. */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const size_t num_points, const u8 *g_scalar, + const smallfelem pre_comp[][17][3]) { + felem nq[3], ftmp; + smallfelem tmp[3]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, 3 * sizeof(felem)); + + /* Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (two in each of the last 32 rounds) and additions of + * other points multiples (every 5th round). */ + + int skip = 1; /* save two point operations in the first round */ + size_t i = num_points != 0 ? 255 : 31; + for (;;) { + /* double */ + if (!skip) { + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + } + + /* add multiples of the generator */ + if (g_scalar != NULL && i <= 31) { + /* first, look 32 bits upwards */ + bits = get_bit(g_scalar, i + 224) << 3; + bits |= get_bit(g_scalar, i + 160) << 2; + bits |= get_bit(g_scalar, i + 96) << 1; + bits |= get_bit(g_scalar, i + 32); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 192) << 3; + bits |= get_bit(g_scalar, i + 128) << 2; + bits |= get_bit(g_scalar, i + 64) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0], + tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points != 0 && i % 5 == 0) { + /* loop over all scalars */ + size_t num; + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* select the point to add or subtract, in constant time. */ + select_point(digit, 17, pre_comp[num], tmp); + smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_small_conditional(ftmp, tmp[1], (((limb)sign) - 1)); + felem_contract(tmp[1], ftmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + } + } + + if (i == 0) { + break; + } + --i; + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} + +/******************************************************************************/ +/* + * OPENSSL EC_METHOD FUNCTIONS + */ + +/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3). */ +static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { + felem z1, z2, x_in, y_in; + smallfelem x_out, y_out; + longfelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + if (!BN_to_felem(x_in, &point->X) || + !BN_to_felem(y_in, &point->Y) || + !BN_to_felem(z1, &point->Z)) { + return 0; + } + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + + if (x != NULL) { + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (!smallfelem_to_BN(x, x_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + } + + if (y != NULL) { + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (!smallfelem_to_BN(y, y_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + } + + return 1; +} + +static int ec_GFp_nistp256_points_mul(const EC_GROUP *group, + EC_POINT *r, + const BIGNUM *g_scalar, + const EC_POINT *p_, + const BIGNUM *p_scalar_, + BN_CTX *ctx) { + /* TODO: This function used to take |points| and |scalars| as arrays of + * |num| elements. The code below should be simplified to work in terms of |p| + * and |p_scalar|. */ + size_t num = p_ != NULL ? 1 : 0; + const EC_POINT **points = p_ != NULL ? &p_ : NULL; + BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL; + + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + smallfelem(*pre_comp)[17][3] = NULL; + felem_bytearray tmp; + size_t num_points = num; + smallfelem x_in, y_in, z_in; + felem x_out, y_out, z_out; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + if ((x = BN_CTX_get(ctx)) == NULL || + (y = BN_CTX_get(ctx)) == NULL || + (z = BN_CTX_get(ctx)) == NULL || + (tmp_scalar = BN_CTX_get(ctx)) == NULL) { + goto err; + } + + if (num_points > 0) { + secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); + pre_comp = OPENSSL_malloc(num_points * sizeof(smallfelem[17][3])); + if (secrets == NULL || pre_comp == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination. */ + memset(secrets, 0, num_points * sizeof(felem_bytearray)); + memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem)); + size_t i; + for (i = 0; i < num_points; ++i) { + if (i == num) { + /* we didn't have a valid precomputation, so we pick the generator. */ + p = EC_GROUP_get0_generator(group); + p_scalar = g_scalar; + } else { + /* the i^th point */ + p = points[i]; + p_scalar = scalars[i]; + } + if (p_scalar != NULL && p != NULL) { + size_t num_bytes; + /* reduce g_scalar to 0 <= g_scalar < 2^256 */ + if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) { + /* this is an unusual input, and we don't guarantee + * constant-timeness. */ + if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(p_scalar, tmp); + } + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if (!BN_to_felem(x_out, &p->X) || + !BN_to_felem(y_out, &p->Y) || + !BN_to_felem(z_out, &p->Z)) { + goto err; + } + felem_shrink(pre_comp[i][1][0], x_out); + felem_shrink(pre_comp[i][1][1], y_out); + felem_shrink(pre_comp[i][1][2], z_out); + size_t j; + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add_small(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], + pre_comp[i][j - 1][0], pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double_small(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], pre_comp[i][j / 2][2]); + } + } + } + } + } + + if (g_scalar != NULL) { + size_t num_bytes; + + memset(g_secret, 0, sizeof(g_secret)); + /* reduce g_scalar to 0 <= g_scalar < 2^256 */ + if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) { + /* this is an unusual input, and we don't guarantee + * constant-timeness. */ + if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(g_scalar, tmp); + } + flip_endian(g_secret, tmp, num_bytes); + } + batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets, + num_points, g_scalar != NULL ? g_secret : NULL, + (const smallfelem(*)[17][3])pre_comp); + + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if (!smallfelem_to_BN(x, x_in) || + !smallfelem_to_BN(y, y_in) || + !smallfelem_to_BN(z, z_in)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + return ret; +} + +const EC_METHOD *EC_GFp_nistp256_method(void) { + static const EC_METHOD ret = { + ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_copy, + ec_GFp_simple_group_set_curve, + ec_GFp_nistp256_point_get_affine_coordinates, + ec_GFp_nistp256_points_mul, + 0 /* check_pub_key_order */, + ec_GFp_simple_field_mul, ec_GFp_simple_field_sqr, + 0 /* field_encode */, 0 /* field_decode */, + }; + + return &ret; +} + +#endif /* 64_BIT && !WINDOWS */ diff --git a/external/boringssl/crypto/ec/p256-x86_64-table.h.REMOVED.git-id b/external/boringssl/crypto/ec/p256-x86_64-table.h.REMOVED.git-id new file mode 100644 index 0000000000..010e9e3ebe --- /dev/null +++ b/external/boringssl/crypto/ec/p256-x86_64-table.h.REMOVED.git-id @@ -0,0 +1 @@ +e4705f8e11a6f57a44b53640beced5cab94a7f2d \ No newline at end of file diff --git a/external/boringssl/crypto/ec/p256-x86_64.c b/external/boringssl/crypto/ec/p256-x86_64.c new file mode 100644 index 0000000000..e1afec4827 --- /dev/null +++ b/external/boringssl/crypto/ec/p256-x86_64.c @@ -0,0 +1,573 @@ +/* Copyright (c) 2014, Intel Corporation. + * + * 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. */ + +/* Developers and authors: + * Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center + * (2) University of Haifa + * Reference: + * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with + * 256 Bit Primes" */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "../bn/internal.h" +#include "../ec/internal.h" +#include "../internal.h" + + +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ + !defined(OPENSSL_SMALL) + + +#define P256_LIMBS (256 / BN_BITS2) + +typedef struct { + BN_ULONG X[P256_LIMBS]; + BN_ULONG Y[P256_LIMBS]; + BN_ULONG Z[P256_LIMBS]; +} P256_POINT; + +typedef struct { + BN_ULONG X[P256_LIMBS]; + BN_ULONG Y[P256_LIMBS]; +} P256_POINT_AFFINE; + +typedef P256_POINT_AFFINE PRECOMP256_ROW[64]; + +/* Functions implemented in assembly */ + +/* Modular neg: res = -a mod P */ +void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]); +/* Montgomery mul: res = a*b*2^-256 mod P */ +void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS], + const BN_ULONG b[P256_LIMBS]); +/* Montgomery sqr: res = a*a*2^-256 mod P */ +void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS]); +/* Convert a number from Montgomery domain, by multiplying with 1 */ +void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG in[P256_LIMBS]); +/* Functions that perform constant time access to the precomputed tables */ +void ecp_nistz256_select_w5(P256_POINT *val, const P256_POINT *in_t, int index); +void ecp_nistz256_select_w7(P256_POINT_AFFINE *val, + const P256_POINT_AFFINE *in_t, int index); + +/* One converted into the Montgomery domain */ +static const BN_ULONG ONE[P256_LIMBS] = { + TOBN(0x00000000, 0x00000001), TOBN(0xffffffff, 0x00000000), + TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0xfffffffe), +}; + +/* Precomputed tables for the default generator */ +#include "p256-x86_64-table.h" + +/* Recode window to a signed digit, see ecp_nistputil.c for details */ +static unsigned booth_recode_w5(unsigned in) { + unsigned s, d; + + s = ~((in >> 5) - 1); + d = (1 << 6) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + return (d << 1) + (s & 1); +} + +static unsigned booth_recode_w7(unsigned in) { + unsigned s, d; + + s = ~((in >> 7) - 1); + d = (1 << 8) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + return (d << 1) + (s & 1); +} + +static void copy_conditional(BN_ULONG dst[P256_LIMBS], + const BN_ULONG src[P256_LIMBS], BN_ULONG move) { + BN_ULONG mask1 = ((BN_ULONG)0) - move; + BN_ULONG mask2 = ~mask1; + + dst[0] = (src[0] & mask1) ^ (dst[0] & mask2); + dst[1] = (src[1] & mask1) ^ (dst[1] & mask2); + dst[2] = (src[2] & mask1) ^ (dst[2] & mask2); + dst[3] = (src[3] & mask1) ^ (dst[3] & mask2); + if (P256_LIMBS == 8) { + dst[4] = (src[4] & mask1) ^ (dst[4] & mask2); + dst[5] = (src[5] & mask1) ^ (dst[5] & mask2); + dst[6] = (src[6] & mask1) ^ (dst[6] & mask2); + dst[7] = (src[7] & mask1) ^ (dst[7] & mask2); + } +} + +void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a); +void ecp_nistz256_point_add(P256_POINT *r, const P256_POINT *a, + const P256_POINT *b); +void ecp_nistz256_point_add_affine(P256_POINT *r, const P256_POINT *a, + const P256_POINT_AFFINE *b); + +/* r = in^-1 mod p */ +static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS], + const BN_ULONG in[P256_LIMBS]) { + /* The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff + ffffffff + We use FLT and used poly-2 as exponent */ + BN_ULONG p2[P256_LIMBS]; + BN_ULONG p4[P256_LIMBS]; + BN_ULONG p8[P256_LIMBS]; + BN_ULONG p16[P256_LIMBS]; + BN_ULONG p32[P256_LIMBS]; + BN_ULONG res[P256_LIMBS]; + int i; + + ecp_nistz256_sqr_mont(res, in); + ecp_nistz256_mul_mont(p2, res, in); /* 3*p */ + + ecp_nistz256_sqr_mont(res, p2); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p4, res, p2); /* f*p */ + + ecp_nistz256_sqr_mont(res, p4); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p8, res, p4); /* ff*p */ + + ecp_nistz256_sqr_mont(res, p8); + for (i = 0; i < 7; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(p16, res, p8); /* ffff*p */ + + ecp_nistz256_sqr_mont(res, p16); + for (i = 0; i < 15; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(p32, res, p16); /* ffffffff*p */ + + ecp_nistz256_sqr_mont(res, p32); + for (i = 0; i < 31; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, in); + + for (i = 0; i < 32 * 4; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p32); + + for (i = 0; i < 32; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p32); + + for (i = 0; i < 16; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p16); + + for (i = 0; i < 8; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p8); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p4); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p2); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(r, res, in); +} + +/* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and + * returns one if it fits. Otherwise it returns zero. */ +static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS], + const BIGNUM *in) { + if (in->top > P256_LIMBS) { + return 0; + } + + memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS); + memcpy(out, in->d, sizeof(BN_ULONG) * in->top); + return 1; +} + +/* r = p * p_scalar */ +static int ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r, + const EC_POINT *p, const BIGNUM *p_scalar, + BN_CTX *ctx) { + assert(p != NULL); + assert(p_scalar != NULL); + + static const unsigned kWindowSize = 5; + static const unsigned kMask = (1 << (5 /* kWindowSize */ + 1)) - 1; + + /* A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should + * add no more than 63 bytes of overhead. Thus, |table| should require + * ~1599 ((96 * 16) + 63) bytes of stack space. */ + alignas(64) P256_POINT table[16]; + uint8_t p_str[33]; + + + int ret = 0; + BN_CTX *new_ctx = NULL; + int ctx_started = 0; + + if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) { + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + ctx = new_ctx; + } + BN_CTX_start(ctx); + ctx_started = 1; + BIGNUM *mod = BN_CTX_get(ctx); + if (mod == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!BN_nnmod(mod, p_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + p_scalar = mod; + } + + int j; + for (j = 0; j < p_scalar->top * BN_BYTES; j += BN_BYTES) { + BN_ULONG d = p_scalar->d[j / BN_BYTES]; + + p_str[j + 0] = d & 0xff; + p_str[j + 1] = (d >> 8) & 0xff; + p_str[j + 2] = (d >> 16) & 0xff; + p_str[j + 3] = (d >>= 24) & 0xff; + if (BN_BYTES == 8) { + d >>= 8; + p_str[j + 4] = d & 0xff; + p_str[j + 5] = (d >> 8) & 0xff; + p_str[j + 6] = (d >> 16) & 0xff; + p_str[j + 7] = (d >> 24) & 0xff; + } + } + + for (; j < 33; j++) { + p_str[j] = 0; + } + + /* table[0] is implicitly (0,0,0) (the point at infinity), therefore it is + * not stored. All other values are actually stored with an offset of -1 in + * table. */ + P256_POINT *row = table; + + if (!ecp_nistz256_bignum_to_field_elem(row[1 - 1].X, &p->X) || + !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Y, &p->Y) || + !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Z, &p->Z)) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + ecp_nistz256_point_double(&row[2 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[3 - 1], &row[2 - 1], &row[1 - 1]); + ecp_nistz256_point_double(&row[4 - 1], &row[2 - 1]); + ecp_nistz256_point_double(&row[6 - 1], &row[3 - 1]); + ecp_nistz256_point_double(&row[8 - 1], &row[4 - 1]); + ecp_nistz256_point_double(&row[12 - 1], &row[6 - 1]); + ecp_nistz256_point_add(&row[5 - 1], &row[4 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[7 - 1], &row[6 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[9 - 1], &row[8 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[13 - 1], &row[12 - 1], &row[1 - 1]); + ecp_nistz256_point_double(&row[14 - 1], &row[7 - 1]); + ecp_nistz256_point_double(&row[10 - 1], &row[5 - 1]); + ecp_nistz256_point_add(&row[15 - 1], &row[14 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[11 - 1], &row[10 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]); + + BN_ULONG tmp[P256_LIMBS]; + alignas(32) P256_POINT h; + unsigned index = 255; + unsigned wvalue = p_str[(index - 1) / 8]; + wvalue = (wvalue >> ((index - 1) % 8)) & kMask; + + ecp_nistz256_select_w5(r, table, booth_recode_w5(wvalue) >> 1); + + while (index >= 5) { + if (index != 255) { + unsigned off = (index - 1) / 8; + + wvalue = p_str[off] | p_str[off + 1] << 8; + wvalue = (wvalue >> ((index - 1) % 8)) & kMask; + + wvalue = booth_recode_w5(wvalue); + + ecp_nistz256_select_w5(&h, table, wvalue >> 1); + + ecp_nistz256_neg(tmp, h.Y); + copy_conditional(h.Y, tmp, (wvalue & 1)); + + ecp_nistz256_point_add(r, r, &h); + } + + index -= kWindowSize; + + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + } + + /* Final window */ + wvalue = p_str[0]; + wvalue = (wvalue << 1) & kMask; + + wvalue = booth_recode_w5(wvalue); + + ecp_nistz256_select_w5(&h, table, wvalue >> 1); + + ecp_nistz256_neg(tmp, h.Y); + copy_conditional(h.Y, tmp, wvalue & 1); + + ecp_nistz256_point_add(r, r, &h); + + ret = 1; + +err: + if (ctx_started) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; +} + +static int ecp_nistz256_points_mul( + const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p_, const BIGNUM *p_scalar, BN_CTX *ctx) { + assert((p_ != NULL) == (p_scalar != NULL)); + + static const unsigned kWindowSize = 7; + static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1; + + alignas(32) union { + P256_POINT p; + P256_POINT_AFFINE a; + } t, p; + + int ret = 0; + BN_CTX *new_ctx = NULL; + int ctx_started = 0; + + if (g_scalar != NULL) { + if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) { + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { + goto err; + } + ctx = new_ctx; + } + BN_CTX_start(ctx); + ctx_started = 1; + BIGNUM *tmp_scalar = BN_CTX_get(ctx); + if (tmp_scalar == NULL) { + goto err; + } + + if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + g_scalar = tmp_scalar; + } + + uint8_t p_str[33] = {0}; + int i; + for (i = 0; i < g_scalar->top * BN_BYTES; i += BN_BYTES) { + BN_ULONG d = g_scalar->d[i / BN_BYTES]; + + p_str[i + 0] = d & 0xff; + p_str[i + 1] = (d >> 8) & 0xff; + p_str[i + 2] = (d >> 16) & 0xff; + p_str[i + 3] = (d >>= 24) & 0xff; + if (BN_BYTES == 8) { + d >>= 8; + p_str[i + 4] = d & 0xff; + p_str[i + 5] = (d >> 8) & 0xff; + p_str[i + 6] = (d >> 16) & 0xff; + p_str[i + 7] = (d >> 24) & 0xff; + } + } + + for (; i < (int) sizeof(p_str); i++) { + p_str[i] = 0; + } + + /* First window */ + unsigned wvalue = (p_str[0] << 1) & kMask; + unsigned index = kWindowSize; + + wvalue = booth_recode_w7(wvalue); + + const PRECOMP256_ROW *const precomputed_table = + (const PRECOMP256_ROW *)ecp_nistz256_precomputed; + ecp_nistz256_select_w7(&p.a, precomputed_table[0], wvalue >> 1); + + ecp_nistz256_neg(p.p.Z, p.p.Y); + copy_conditional(p.p.Y, p.p.Z, wvalue & 1); + + memcpy(p.p.Z, ONE, sizeof(ONE)); + + for (i = 1; i < 37; i++) { + unsigned off = (index - 1) / 8; + wvalue = p_str[off] | p_str[off + 1] << 8; + wvalue = (wvalue >> ((index - 1) % 8)) & kMask; + index += kWindowSize; + + wvalue = booth_recode_w7(wvalue); + + ecp_nistz256_select_w7(&t.a, precomputed_table[i], wvalue >> 1); + + ecp_nistz256_neg(t.p.Z, t.a.Y); + copy_conditional(t.a.Y, t.p.Z, wvalue & 1); + + ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a); + } + } + + const int p_is_infinity = g_scalar == NULL; + if (p_scalar != NULL) { + P256_POINT *out = &t.p; + if (p_is_infinity) { + out = &p.p; + } + + if (!ecp_nistz256_windowed_mul(group, out, p_, p_scalar, ctx)) { + goto err; + } + + if (!p_is_infinity) { + ecp_nistz256_point_add(&p.p, &p.p, out); + } + } + + /* Not constant-time, but we're only operating on the public output. */ + if (!bn_set_words(&r->X, p.p.X, P256_LIMBS) || + !bn_set_words(&r->Y, p.p.Y, P256_LIMBS) || + !bn_set_words(&r->Z, p.p.Z, P256_LIMBS)) { + return 0; + } + + ret = 1; + +err: + if (ctx_started) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; +} + +static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { + BN_ULONG z_inv2[P256_LIMBS]; + BN_ULONG z_inv3[P256_LIMBS]; + BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS]; + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + + if (!ecp_nistz256_bignum_to_field_elem(point_x, &point->X) || + !ecp_nistz256_bignum_to_field_elem(point_y, &point->Y) || + !ecp_nistz256_bignum_to_field_elem(point_z, &point->Z)) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + return 0; + } + + ecp_nistz256_mod_inverse(z_inv3, point_z); + ecp_nistz256_sqr_mont(z_inv2, z_inv3); + + /* Instead of using |ecp_nistz256_from_mont| to convert the |x| coordinate + * and then calling |ecp_nistz256_from_mont| again to convert the |y| + * coordinate below, convert the common factor |z_inv2| once now, saving one + * reduction. */ + ecp_nistz256_from_mont(z_inv2, z_inv2); + + if (x != NULL) { + if (bn_wexpand(x, P256_LIMBS) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return 0; + } + x->top = P256_LIMBS; + x->neg = 0; + ecp_nistz256_mul_mont(x->d, z_inv2, point_x); + bn_correct_top(x); + } + + if (y != NULL) { + ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2); + if (bn_wexpand(y, P256_LIMBS) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return 0; + } + y->top = P256_LIMBS; + y->neg = 0; + ecp_nistz256_mul_mont(y->d, z_inv3, point_y); + bn_correct_top(y); + } + + return 1; +} + +const EC_METHOD *EC_GFp_nistz256_method(void) { + static const EC_METHOD ret = { + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve, + ecp_nistz256_get_affine, + ecp_nistz256_points_mul, + 0 /* check_pub_key_order */, + ec_GFp_mont_field_mul, + ec_GFp_mont_field_sqr, + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + }; + + return &ret; +} + +#endif /* !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ + !defined(OPENSSL_SMALL) */ diff --git a/external/boringssl/crypto/ec/simple.c b/external/boringssl/crypto/ec/simple.c new file mode 100644 index 0000000000..4508d83fb6 --- /dev/null +++ b/external/boringssl/crypto/ec/simple.c @@ -0,0 +1,1112 @@ +/* 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 + +#include + +#include +#include +#include + +#include "internal.h" + + +/* Most method functions in this file are designed to work with non-trivial + * representations of field elements if necessary (see ecp_mont.c): while + * standard modular addition and subtraction are used, the field_mul and + * field_sqr methods will be used for multiplication, and field_encode and + * field_decode (if defined) will be used for converting between + * representations. + * + * Functions here 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); + BN_init(&group->one); + 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); + BN_free(&group->one); +} + +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) || + !BN_copy(&dest->one, &src->one)) { + 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_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 && + !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)); + + if (group->meth->field_encode != NULL) { + if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) { + goto err; + } + } else if (!BN_copy(&group->one, BN_value_one())) { + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + 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 && !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 && !group->meth->field_decode(group, a, &group->a, ctx)) { + goto err; + } + if (b != NULL && !group->meth->field_decode(group, b, &group->b, ctx)) { + goto err; + } + } else { + if (a != NULL && !BN_copy(a, &group->a)) { + goto err; + } + if (b != NULL && !BN_copy(b, &group->b)) { + goto err; + } + } + } + + ret = 1; + +err: + BN_CTX_free(new_ctx); + return ret; +} + +unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *group) { + return BN_num_bits(&group->field); +} + +int ec_GFp_simple_point_init(EC_POINT *point) { + BN_init(&point->X); + BN_init(&point->Y); + BN_init(&point->Z); + + 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); +} + +int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) { + if (!BN_copy(&dest->X, &src->X) || + !BN_copy(&dest->Y, &src->Y) || + !BN_copy(&dest->Z, &src->Z)) { + return 0; + } + + return 1; +} + +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) { + BN_zero(&point->Z); + return 1; +} + +static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out, + const BIGNUM *in, BN_CTX *ctx) { + if (in == NULL) { + return 1; + } + if (BN_is_negative(in) || + BN_cmp(in, &group->field) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + return 0; + } + if (group->meth->field_encode) { + return group->meth->field_encode(group, out, in, ctx); + } + return BN_copy(out, in) != NULL; +} + +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 (!set_Jprojective_coordinate_GFp(group, &point->X, x, ctx) || + !set_Jprojective_coordinate_GFp(group, &point->Y, y, ctx) || + !set_Jprojective_coordinate_GFp(group, &point->Z, z, ctx)) { + goto err; + } + + ret = 1; + +err: + 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 && !group->meth->field_decode(group, x, &point->X, ctx)) { + goto err; + } + if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) { + goto err; + } + if (z != NULL && !group->meth->field_decode(group, z, &point->Z, ctx)) { + goto err; + } + } else { + if (x != NULL && !BN_copy(x, &point->X)) { + goto err; + } + if (y != NULL && !BN_copy(y, &point->Y)) { + goto err; + } + if (z != NULL && !BN_copy(z, &point->Z)) { + goto err; + } + } + + ret = 1; + +err: + 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, 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_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 */ + int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0; + + if (b_Z_is_one) { + if (!BN_copy(n1, &a->X) || !BN_copy(n2, &a->Y)) { + goto end; + } + /* n1 = X_a */ + /* n2 = Y_a */ + } else { + if (!field_sqr(group, n0, &b->Z, ctx) || + !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) || + !field_mul(group, n2, &a->Y, n0, ctx)) { + goto end; + } + /* n2 = Y_a * Z_b^3 */ + } + + /* n3, n4 */ + int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0; + if (a_Z_is_one) { + if (!BN_copy(n3, &b->X) || !BN_copy(n4, &b->Y)) { + goto end; + } + /* n3 = X_b */ + /* n4 = Y_b */ + } else { + if (!field_sqr(group, n0, &a->Z, ctx) || + !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) || + !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) || + !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); + ret = 1; + goto end; + } + } + + /* 'n7', 'n8' */ + if (!BN_mod_add_quick(n1, n1, n3, p) || + !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; + } + } + + /* Z_r = Z_a * Z_b * n5 */ + + /* X_r */ + if (!field_sqr(group, n0, n6, ctx) || + !field_sqr(group, n4, n5, ctx) || + !field_mul(group, n3, n1, n4, ctx) || + !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) || + !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) || + !field_mul(group, n5, n4, n5, ctx)) { + goto end; /* now n5 is n5^3 */ + } + if (!field_mul(group, n1, n2, n5, ctx) || + !BN_mod_sub_quick(n0, n0, n1, p)) { + goto end; + } + if (BN_is_odd(n0) && !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); + } + 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); + 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 (BN_cmp(&a->Z, &group->one) == 0) { + if (!field_sqr(group, n0, &a->X, ctx) || + !BN_mod_lshift1_quick(n1, n0, p) || + !BN_mod_add_quick(n0, n0, n1, p) || + !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) || + !BN_mod_add_quick(n0, &a->X, n1, p) || + !BN_mod_sub_quick(n2, &a->X, n1, p) || + !field_mul(group, n1, n0, n2, ctx) || + !BN_mod_lshift1_quick(n0, n1, p) || + !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) || + !BN_mod_lshift1_quick(n1, n0, p) || + !BN_mod_add_quick(n0, n0, n1, p) || + !field_sqr(group, n1, &a->Z, ctx) || + !field_sqr(group, n1, n1, ctx) || + !field_mul(group, n1, n1, &group->a, ctx) || + !BN_mod_add_quick(n1, n1, n0, p)) { + goto err; + } + /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ + } + + /* Z_r */ + if (BN_cmp(&a->Z, &group->one) == 0) { + 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; + } + /* Z_r = 2 * Y_a * Z_a */ + + /* n2 */ + if (!field_sqr(group, n3, &a->Y, ctx) || + !field_mul(group, n2, &a->X, n3, ctx) || + !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) || + !field_sqr(group, &r->X, n1, ctx) || + !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) || + !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) || + !field_mul(group, n0, n1, n0, ctx) || + !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); + 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 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 = 0; + + 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 0; + } + } + + 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 (BN_cmp(&point->Z, &group->one) != 0) { + if (!field_sqr(group, tmp, &point->Z, ctx) || + !field_sqr(group, Z4, tmp, ctx) || + !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) || + !BN_mod_add_quick(tmp, tmp, Z4, p) || + !BN_mod_sub_quick(rh, rh, tmp, p) || + !field_mul(group, rh, rh, &point->X, ctx)) { + goto err; + } + } else { + if (!field_mul(group, tmp, Z4, &group->a, ctx) || + !BN_mod_add_quick(rh, rh, tmp, p) || + !field_mul(group, rh, rh, &point->X, ctx)) { + goto err; + } + } + + /* rh := rh + b*Z^6 */ + if (!field_mul(group, tmp, &group->b, Z6, ctx) || + !BN_mod_add_quick(rh, rh, tmp, p)) { + goto err; + } + } else { + /* rh := (rh + a)*X */ + if (!BN_mod_add_quick(rh, rh, &group->a, p) || + !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); + 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; + } + + int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0; + int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0; + + 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) || + !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) || + !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) || + !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) || + !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); + 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 (BN_cmp(&point->Z, &group->one) == 0 || + 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) || + !EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + goto err; + } + if (BN_cmp(&point->Z, &group->one) != 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + 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 (BN_copy(prod_Z[0], &group->one) == NULL) { + 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, 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 (BN_copy(&p->Z, &group->one) == NULL) { + goto err; + } + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + 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/external/boringssl/crypto/ec/util-64.c b/external/boringssl/crypto/ec/util-64.c new file mode 100644 index 0000000000..4006271253 --- /dev/null +++ b/external/boringssl/crypto/ec/util-64.c @@ -0,0 +1,109 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + + +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) + +#include + +#include "internal.h" + +/* This function looks at 5+1 scalar bits (5 current, 1 adjacent less + * significant bit), and recodes them into a signed digit for use in fast point + * multiplication: the use of signed rather than unsigned digits means that + * fewer points need to be precomputed, given that point inversion is easy (a + * precomputed point dP makes -dP available as well). + * + * BACKGROUND: + * + * Signed digits for multiplication were introduced by Booth ("A signed binary + * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV, + * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers. + * Booth's original encoding did not generally improve the density of nonzero + * digits over the binary representation, and was merely meant to simplify the + * handling of signed factors given in two's complement; but it has since been + * shown to be the basis of various signed-digit representations that do have + * further advantages, including the wNAF, using the following general + * approach: + * + * (1) Given a binary representation + * + * b_k ... b_2 b_1 b_0, + * + * of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1 + * by using bit-wise subtraction as follows: + * + * b_k b_(k-1) ... b_2 b_1 b_0 + * - b_k ... b_3 b_2 b_1 b_0 + * ------------------------------------- + * s_k b_(k-1) ... s_3 s_2 s_1 s_0 + * + * A left-shift followed by subtraction of the original value yields a new + * representation of the same value, using signed bits s_i = b_(i+1) - b_i. + * This representation from Booth's paper has since appeared in the + * literature under a variety of different names including "reversed binary + * form", "alternating greedy expansion", "mutual opposite form", and + * "sign-alternating {+-1}-representation". + * + * An interesting property is that among the nonzero bits, values 1 and -1 + * strictly alternate. + * + * (2) Various window schemes can be applied to the Booth representation of + * integers: for example, right-to-left sliding windows yield the wNAF + * (a signed-digit encoding independently discovered by various researchers + * in the 1990s), and left-to-right sliding windows yield a left-to-right + * equivalent of the wNAF (independently discovered by various researchers + * around 2004). + * + * To prevent leaking information through side channels in point multiplication, + * we need to recode the given integer into a regular pattern: sliding windows + * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few + * decades older: we'll be using the so-called "modified Booth encoding" due to + * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49 + * (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five + * signed bits into a signed digit: + * + * s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j) + * + * The sign-alternating property implies that the resulting digit values are + * integers from -16 to 16. + * + * Of course, we don't actually need to compute the signed digits s_i as an + * intermediate step (that's just a nice way to see how this scheme relates + * to the wNAF): a direct computation obtains the recoded digit from the + * six bits b_(4j + 4) ... b_(4j - 1). + * + * This function takes those five bits as an integer (0 .. 63), writing the + * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute + * value, in the range 0 .. 8). Note that this integer essentially provides the + * input bits "shifted to the left" by one position: for example, the input to + * compute the least significant recoded digit, given that there's no bit b_-1, + * has to be b_4 b_3 b_2 b_1 b_0 0. */ +void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, + uint8_t in) { + uint8_t s, d; + + s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as + * 6-bit value */ + d = (1 << 6) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + *sign = s & 1; + *digit = d; +} + +#endif /* 64_BIT && !WINDOWS */ diff --git a/external/boringssl/crypto/ec/wnaf.c b/external/boringssl/crypto/ec/wnaf.c new file mode 100644 index 0000000000..ba2257c46f --- /dev/null +++ b/external/boringssl/crypto/ec/wnaf.c @@ -0,0 +1,449 @@ +/* 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 + +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +/* This file implements the wNAF-based interleaving multi-exponentation method + * (); + * */ + +/* 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, 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, 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, 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, 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, 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, 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, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (j > len + 1) { + OPENSSL_PUT_ERROR(EC, 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)) + +int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + const EC_POINT *generator = NULL; + EC_POINT *tmp = NULL; + size_t total_num; + 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' */ + int ret = 0; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + } + + /* TODO: This function used to take |points| and |scalars| as arrays of + * |num| elements. The code below should be simplified to work in terms of |p| + * and |p_scalar|. */ + size_t num = p != NULL ? 1 : 0; + const EC_POINT **points = p != NULL ? &p : NULL; + const BIGNUM **scalars = p != NULL ? &p_scalar : NULL; + + total_num = num; + + if (g_scalar != NULL) { + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + ++total_num; /* treat 'g_scalar' like 'num'-th element of 'scalars' */ + } + + + wsize = OPENSSL_malloc(total_num * sizeof wsize[0]); + wNAF_len = OPENSSL_malloc(total_num * sizeof wNAF_len[0]); + wNAF = OPENSSL_malloc((total_num + 1) * + sizeof wNAF[0]); /* includes space for pivot */ + val_sub = OPENSSL_malloc(total_num * 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, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* num_val will be the total number of temporarily precomputed points */ + num_val = 0; + + for (i = 0; i < total_num; i++) { + size_t bits; + + bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(g_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] : g_scalar), wsize[i], &wNAF_len[i]); + if (wNAF[i] == NULL) { + goto err; + } + if (wNAF_len[i] > max_len) { + max_len = wNAF_len[i]; + } + } + + /* 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. */ + val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); + if (val == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + val[num_val] = NULL; /* pivot element */ + + /* allocate points for precomputation */ + v = val; + for (i = 0; i < total_num; 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, 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 < total_num; 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 && !EC_POINT_dbl(group, r, r, ctx)) { + goto err; + } + + for (i = 0; i < total_num; 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 && !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 && !EC_POINT_invert(group, r, ctx)) { + goto err; + } + + ret = 1; + +err: + BN_CTX_free(new_ctx); + EC_POINT_free(tmp); + OPENSSL_free(wsize); + 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); + } + OPENSSL_free(val_sub); + return ret; +} diff --git a/external/boringssl/crypto/ecdh/CMakeLists.txt b/external/boringssl/crypto/ecdh/CMakeLists.txt new file mode 100644 index 0000000000..8eaeae5e70 --- /dev/null +++ b/external/boringssl/crypto/ecdh/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + ecdh + + OBJECT + + ecdh.c +) diff --git a/external/boringssl/crypto/ecdh/ecdh.c b/external/boringssl/crypto/ecdh/ecdh.c new file mode 100644 index 0000000000..4a1964a0b3 --- /dev/null +++ b/external/boringssl/crypto/ecdh/ecdh.c @@ -0,0 +1,153 @@ +/* ==================================================================== + * 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 + +#include + +#include +#include +#include +#include + + +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)) { + const BIGNUM *const priv = EC_KEY_get0_private_key(priv_key); + if (priv == NULL) { + OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE); + return -1; + } + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return -1; + } + BN_CTX_start(ctx); + + int ret = -1; + size_t buflen = 0; + uint8_t *buf = NULL; + + const EC_GROUP *const group = EC_KEY_get0_group(priv_key); + EC_POINT *tmp = EC_POINT_new(group); + if (tmp == NULL) { + OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv, ctx)) { + OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); + goto err; + } + + BIGNUM *x = BN_CTX_get(ctx); + if (!x) { + OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, NULL, ctx)) { + OPENSSL_PUT_ERROR(ECDH, 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, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BN_bn2bin_padded(buf, buflen, x)) { + OPENSSL_PUT_ERROR(ECDH, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (kdf != NULL) { + if (kdf(buf, buflen, out, &outlen) == NULL) { + OPENSSL_PUT_ERROR(ECDH, ECDH_R_KDF_FAILED); + goto err; + } + } else { + /* no KDF, just copy as much as we can */ + if (buflen < outlen) { + outlen = buflen; + } + memcpy(out, buf, outlen); + } + + ret = outlen; + +err: + OPENSSL_free(buf); + EC_POINT_free(tmp); + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} diff --git a/external/boringssl/crypto/ecdsa/CMakeLists.txt b/external/boringssl/crypto/ecdsa/CMakeLists.txt new file mode 100644 index 0000000000..f9af1ed714 --- /dev/null +++ b/external/boringssl/crypto/ecdsa/CMakeLists.txt @@ -0,0 +1,24 @@ +include_directories(../../include) + +add_library( + ecdsa + + OBJECT + + ecdsa.c + ecdsa_asn1.c +) + + +if(ENABLE_TESTS) +add_executable( + ecdsa_test + + ecdsa_test.cc + + $ +) + +target_link_libraries(ecdsa_test crypto) +add_dependencies(all_tests ecdsa_test) +endif() diff --git a/external/boringssl/crypto/ecdsa/ecdsa.c b/external/boringssl/crypto/ecdsa/ecdsa.c new file mode 100644 index 0000000000..70cb11897b --- /dev/null +++ b/external/boringssl/crypto/ecdsa/ecdsa.c @@ -0,0 +1,487 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include + +#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; + + /* Decode the ECDSA signature. */ + s = ECDSA_SIG_from_bytes(sig, sig_len); + if (s == NULL) { + goto err; + } + + /* Defend against potential laxness in the DER parser. */ + size_t der_len; + if (!ECDSA_SIG_to_bytes(&der, &der_len, s) || + der_len != sig_len || memcmp(sig, der, sig_len) != 0) { + /* This should never happen. crypto/bytestring is strictly DER. */ + OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = ECDSA_do_verify(digest, digest_len, s, eckey); + +err: + OPENSSL_free(der); + 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, 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, 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 *u1, *u2, *m, *X; + EC_POINT *point = NULL; + const EC_GROUP *group; + const EC_POINT *pub_key; + + /* 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_R_MISSING_PARAMETERS); + return 0; + } + + ctx = BN_CTX_new(); + if (!ctx) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + return 0; + } + BN_CTX_start(ctx); + u1 = BN_CTX_get(ctx); + u2 = BN_CTX_get(ctx); + m = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + if (u1 == NULL || u2 == NULL || m == NULL || X == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + + const BIGNUM *order = EC_GROUP_get0_order(group); + 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_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, 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, 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, ERR_R_BN_LIB); + goto err; + } + + point = EC_POINT_new(group); + if (point == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + if (!BN_nnmod(u1, X, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, 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); + 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, *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, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ctx_in == NULL) { + if ((ctx = BN_CTX_new()) == NULL) { + OPENSSL_PUT_ERROR(ECDSA, 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 */ + X = BN_new(); + if (k == NULL || r == NULL || X == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + tmp_point = EC_POINT_new(group); + if (tmp_point == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + + const BIGNUM *order = EC_GROUP_get0_order(group); + + 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_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, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + + if (!BN_nnmod(r, X, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + } while (BN_is_zero(r)); + + /* compute the inverse of k */ + if (ec_group_get_mont_data(group) != NULL) { + /* We want inverse in constant time, therefore we use that the order must + * be prime and thus we can use Fermat's Little Theorem. */ + if (!BN_set_word(X, 2) || + !BN_sub(X, order, X)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + BN_set_flags(X, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(k, k, X, order, ctx, + ec_group_get_mont_data(group))) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + } else if (!BN_mod_inverse(k, k, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + /* clear old values if necessary */ + BN_clear_free(*rp); + BN_clear_free(*kinvp); + + /* save the pre-computed values */ + *rp = r; + *kinvp = k; + ret = 1; + +err: + if (!ret) { + BN_clear_free(k); + BN_clear_free(r); + } + if (ctx_in == NULL) { + BN_CTX_free(ctx); + } + EC_POINT_free(tmp_point); + 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; + 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_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, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ret = ECDSA_SIG_new(); + if (!ret) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + s = ret->s; + + if ((ctx = BN_CTX_new()) == NULL || + (tmp = BN_new()) == NULL || + (m = BN_new()) == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + const BIGNUM *order = EC_GROUP_get0_order(group); + + 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, ERR_R_ECDSA_LIB); + goto err; + } + ckinv = kinv; + } else { + ckinv = in_kinv; + if (BN_copy(ret->r, in_r) == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + if (!BN_mod_add_quick(s, tmp, m, order)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + if (!BN_mod_mul(s, s, ckinv, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, 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_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; + } + BN_CTX_free(ctx); + BN_clear_free(m); + BN_clear_free(tmp); + 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) { + int ret = 0; + ECDSA_SIG *s = NULL; + + if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED); + *sig_len = 0; + goto err; + } + + s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey); + if (s == NULL) { + *sig_len = 0; + goto err; + } + + CBB cbb; + CBB_zero(&cbb); + size_t len; + if (!CBB_init_fixed(&cbb, sig, ECDSA_size(eckey)) || + !ECDSA_SIG_marshal(&cbb, s) || + !CBB_finish(&cbb, NULL, &len)) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + *sig_len = 0; + goto err; + } + *sig_len = (unsigned)len; + ret = 1; + +err: + ECDSA_SIG_free(s); + return ret; +} diff --git a/external/boringssl/crypto/ecdsa/ecdsa_asn1.c b/external/boringssl/crypto/ecdsa/ecdsa_asn1.c new file mode 100644 index 0000000000..d41a536679 --- /dev/null +++ b/external/boringssl/crypto/ecdsa/ecdsa_asn1.c @@ -0,0 +1,227 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../bytestring/internal.h" +#include "../ec/internal.h" + + +size_t ECDSA_size(const EC_KEY *key) { + if (key == NULL) { + return 0; + } + + size_t group_order_size; + if (key->ecdsa_meth && key->ecdsa_meth->group_order_size) { + group_order_size = key->ecdsa_meth->group_order_size(key); + } else { + const EC_GROUP *group = EC_KEY_get0_group(key); + if (group == NULL) { + return 0; + } + + group_order_size = BN_num_bytes(EC_GROUP_get0_order(group)); + } + + return ECDSA_SIG_max_len(group_order_size); +} + +ECDSA_SIG *ECDSA_SIG_new(void) { + ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG)); + if (sig == NULL) { + return NULL; + } + sig->r = BN_new(); + sig->s = BN_new(); + if (sig->r == NULL || sig->s == NULL) { + ECDSA_SIG_free(sig); + return NULL; + } + return sig; +} + +void ECDSA_SIG_free(ECDSA_SIG *sig) { + if (sig == NULL) { + return; + } + + BN_free(sig->r); + BN_free(sig->s); + OPENSSL_free(sig); +} + +ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) { + ECDSA_SIG *ret = ECDSA_SIG_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !BN_parse_asn1_unsigned(&child, ret->r) || + !BN_parse_asn1_unsigned(&child, ret->s) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); + ECDSA_SIG_free(ret); + return NULL; + } + return ret; +} + +ECDSA_SIG *ECDSA_SIG_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); + ECDSA_SIG_free(ret); + return NULL; + } + return ret; +} + +int ECDSA_SIG_marshal(CBB *cbb, const ECDSA_SIG *sig) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !BN_marshal_asn1(&child, sig->r) || + !BN_marshal_asn1(&child, sig->s) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int ECDSA_SIG_to_bytes(uint8_t **out_bytes, size_t *out_len, + const ECDSA_SIG *sig) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !ECDSA_SIG_marshal(&cbb, sig) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +/* der_len_len returns the number of bytes needed to represent a length of |len| + * in DER. */ +static size_t der_len_len(size_t len) { + if (len < 0x80) { + return 1; + } + size_t ret = 1; + while (len > 0) { + ret++; + len >>= 8; + } + return ret; +} + +size_t ECDSA_SIG_max_len(size_t order_len) { + /* Compute the maximum length of an |order_len| byte integer. Defensively + * assume that the leading 0x00 is included. */ + size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len; + if (integer_len < order_len) { + return 0; + } + /* An ECDSA signature is two INTEGERs. */ + size_t value_len = 2 * integer_len; + if (value_len < integer_len) { + return 0; + } + /* Add the header. */ + size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len; + if (ret < value_len) { + return 0; + } + return ret; +} + +ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + ECDSA_SIG_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !ECDSA_SIG_marshal(&cbb, sig)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} diff --git a/external/boringssl/crypto/ecdsa/ecdsa_test.cc b/external/boringssl/crypto/ecdsa/ecdsa_test.cc new file mode 100644 index 0000000000..8d7827df5e --- /dev/null +++ b/external/boringssl/crypto/ecdsa/ecdsa_test.cc @@ -0,0 +1,363 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + +enum Api { + kEncodedApi, + kRawApi, +}; + +// VerifyECDSASig returns true on success, false on failure. +static bool VerifyECDSASig(Api api, const uint8_t *digest, + size_t digest_len, const ECDSA_SIG *ecdsa_sig, + EC_KEY *eckey, int expected_result) { + int actual_result; + + switch (api) { + case kEncodedApi: { + uint8_t *der; + size_t der_len; + if (!ECDSA_SIG_to_bytes(&der, &der_len, ecdsa_sig)) { + return false; + } + ScopedOpenSSLBytes delete_der(der); + actual_result = ECDSA_verify(0, digest, digest_len, der, der_len, eckey); + break; + } + + case kRawApi: + actual_result = ECDSA_do_verify(digest, digest_len, ecdsa_sig, eckey); + break; + + default: + return false; + } + return expected_result == actual_result; +} + +// TestTamperedSig verifies that signature verification fails when a valid +// signature is tampered with. |ecdsa_sig| must be a valid signature, which will +// be modified. TestTamperedSig returns true on success, false on failure. +static bool TestTamperedSig(FILE *out, Api api, const uint8_t *digest, + size_t digest_len, ECDSA_SIG *ecdsa_sig, + EC_KEY *eckey, const BIGNUM *order) { + // 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. + + // Store the two BIGNUMs in raw_buf. + size_t r_len = BN_num_bytes(ecdsa_sig->r); + size_t s_len = BN_num_bytes(ecdsa_sig->s); + size_t bn_len = BN_num_bytes(order); + if (r_len > bn_len || s_len > bn_len) { + return false; + } + size_t buf_len = 2 * bn_len; + std::vector raw_buf(buf_len); + // Pad the bignums with leading zeroes. + if (!BN_bn2bin_padded(raw_buf.data(), bn_len, ecdsa_sig->r) || + !BN_bn2bin_padded(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s)) { + return false; + } + + // Modify a single byte in the buffer. + size_t offset = raw_buf[10] % buf_len; + uint8_t 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.data(), bn_len, ecdsa_sig->r) == NULL || + BN_bin2bn(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s) == NULL || + !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 0)) { + return false; + } + + // Sanity check: Undo the modification and verify signature. + raw_buf[offset] ^= dirt; + if (BN_bin2bn(raw_buf.data(), bn_len, ecdsa_sig->r) == NULL || + BN_bin2bn(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s) == NULL || + !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 1)) { + return false; + } + + return true; +} + +static bool TestBuiltin(FILE *out) { + // Fill digest values with some random data. + uint8_t digest[20], wrong_digest[20]; + if (!RAND_bytes(digest, 20) || !RAND_bytes(wrong_digest, 20)) { + fprintf(out, "ERROR: unable to get random data\n"); + return false; + } + + static const struct { + int nid; + const char *name; + } kCurves[] = { + { NID_secp224r1, "secp224r1" }, + { NID_X9_62_prime256v1, "secp256r1" }, + { NID_secp384r1, "secp384r1" }, + { NID_secp521r1, "secp521r1" }, + { NID_undef, NULL } + }; + + // Create and verify ECDSA signatures with every available curve. + fputs("\ntesting ECDSA_sign(), ECDSA_verify(), ECDSA_do_sign(), and " + "ECDSA_do_verify() with some internal curves:\n", out); + + for (size_t n = 0; kCurves[n].nid != NID_undef; n++) { + fprintf(out, "%s: ", kCurves[n].name); + + int nid = kCurves[n].nid; + ScopedEC_GROUP group(EC_GROUP_new_by_curve_name(nid)); + if (!group) { + fprintf(out, " failed\n"); + return false; + } + const BIGNUM *order = EC_GROUP_get0_order(group.get()); + if (BN_num_bits(order) < 160) { + // Too small to test. + fprintf(out, " skipped\n"); + continue; + } + + // Create a new ECDSA key. + ScopedEC_KEY eckey(EC_KEY_new()); + if (!eckey || !EC_KEY_set_group(eckey.get(), group.get()) || + !EC_KEY_generate_key(eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + // Create a second key. + ScopedEC_KEY wrong_eckey(EC_KEY_new()); + if (!wrong_eckey || !EC_KEY_set_group(wrong_eckey.get(), group.get()) || + !EC_KEY_generate_key(wrong_eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + + fprintf(out, "."); + fflush(out); + + // Check the key. + if (!EC_KEY_check_key(eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + + // Test ASN.1-encoded signatures. + // Create a signature. + unsigned sig_len = ECDSA_size(eckey.get()); + std::vector signature(sig_len); + if (!ECDSA_sign(0, digest, 20, signature.data(), &sig_len, eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + signature.resize(sig_len); + fprintf(out, "."); + fflush(out); + // Verify the signature. + if (!ECDSA_verify(0, digest, 20, signature.data(), signature.size(), + eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature with the wrong key. + if (ECDSA_verify(0, digest, 20, signature.data(), signature.size(), + wrong_eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature using the wrong digest. + if (ECDSA_verify(0, wrong_digest, 20, signature.data(), signature.size(), + eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify a truncated signature. + if (ECDSA_verify(0, digest, 20, signature.data(), signature.size() - 1, + eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify a tampered signature. + ScopedECDSA_SIG ecdsa_sig(ECDSA_SIG_from_bytes( + signature.data(), signature.size())); + if (!ecdsa_sig || + !TestTamperedSig(out, kEncodedApi, digest, 20, ecdsa_sig.get(), + eckey.get(), order)) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + + // Test ECDSA_SIG signing and verification. + // Create a signature. + ecdsa_sig.reset(ECDSA_do_sign(digest, 20, eckey.get())); + if (!ecdsa_sig) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature using the correct key. + if (!ECDSA_do_verify(digest, 20, ecdsa_sig.get(), eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature with the wrong key. + if (ECDSA_do_verify(digest, 20, ecdsa_sig.get(), wrong_eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature using the wrong digest. + if (ECDSA_do_verify(wrong_digest, 20, ecdsa_sig.get(), eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify a tampered signature. + if (!TestTamperedSig(out, kRawApi, digest, 20, ecdsa_sig.get(), eckey.get(), + order)) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + + fprintf(out, " ok\n"); + // Clear bogus errors. + ERR_clear_error(); + } + + return true; +} + +static bool TestECDSA_SIG_max_len(size_t order_len) { + /* Create the largest possible |ECDSA_SIG| of the given constraints. */ + ScopedECDSA_SIG sig(ECDSA_SIG_new()); + if (!sig) { + return false; + } + std::vector bytes(order_len, 0xff); + if (!BN_bin2bn(bytes.data(), bytes.size(), sig->r) || + !BN_bin2bn(bytes.data(), bytes.size(), sig->s)) { + return false; + } + /* Serialize it. */ + uint8_t *der; + size_t der_len; + if (!ECDSA_SIG_to_bytes(&der, &der_len, sig.get())) { + return false; + } + ScopedOpenSSLBytes delete_der(der); + + size_t max_len = ECDSA_SIG_max_len(order_len); + if (max_len != der_len) { + fprintf(stderr, "ECDSA_SIG_max_len(%u) returned %u, wanted %u\n", + static_cast(order_len), static_cast(max_len), + static_cast(der_len)); + return false; + } + return true; +} + +static size_t BitsToBytes(size_t bits) { + return (bits / 8) + (7 + (bits % 8)) / 8; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestBuiltin(stdout) || + !TestECDSA_SIG_max_len(BitsToBytes(224)) || + !TestECDSA_SIG_max_len(BitsToBytes(256)) || + !TestECDSA_SIG_max_len(BitsToBytes(384)) || + !TestECDSA_SIG_max_len(BitsToBytes(521)) || + !TestECDSA_SIG_max_len(BitsToBytes(10000))) { + printf("\nECDSA test failed\n"); + ERR_print_errors_fp(stdout); + return 1; + } + + printf("\nPASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/engine/CMakeLists.txt b/external/boringssl/crypto/engine/CMakeLists.txt new file mode 100644 index 0000000000..5667f02348 --- /dev/null +++ b/external/boringssl/crypto/engine/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + engine + + OBJECT + + engine.c +) diff --git a/external/boringssl/crypto/engine/engine.c b/external/boringssl/crypto/engine/engine.c new file mode 100644 index 0000000000..25ea98de2e --- /dev/null +++ b/external/boringssl/crypto/engine/engine.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + + +struct engine_st { + 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) { + /* Methods are currently required to be static so are not unref'ed. */ + OPENSSL_free(engine); +} + +/* set_method takes a pointer to a method and its given size and sets + * |*out_member| to point to it. This function might want to be extended in the + * future to support making a copy of the method so that a stable ABI for + * ENGINEs can be supported. But, for the moment, all *_METHODS must be + * static. */ +static int set_method(void **out_member, const void *method, size_t method_size, + size_t compiled_size) { + const struct openssl_method_common_st *common = method; + if (method_size != compiled_size || !common->is_static) { + return 0; + } + + *out_member = (void*) method; + return 1; +} + +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) { + assert(((struct openssl_method_common_st*) method_in)->is_static); +} + +void METHOD_unref(void *method_in) { + struct openssl_method_common_st *method = method_in; + + if (method == NULL) { + return; + } + assert(method->is_static); +} + +OPENSSL_DECLARE_ERROR_REASON(ENGINE, OPERATION_NOT_SUPPORTED); diff --git a/external/boringssl/crypto/err/CMakeLists.txt b/external/boringssl/crypto/err/CMakeLists.txt new file mode 100644 index 0000000000..9151088194 --- /dev/null +++ b/external/boringssl/crypto/err/CMakeLists.txt @@ -0,0 +1,52 @@ +include_directories(../../include) + +#add_custom_command( +# OUTPUT err_data.c +# COMMAND ${GO_EXECUTABLE} run err_data_generate.go > ${CMAKE_CURRENT_BINARY_DIR}/err_data.c +# DEPENDS +# err_data_generate.go +# asn1.errordata +# bio.errordata +# bn.errordata +# cipher.errordata +# conf.errordata +# dh.errordata +# digest.errordata +# dsa.errordata +# ecdh.errordata +# ecdsa.errordata +# ec.errordata +# engine.errordata +# evp.errordata +# hkdf.errordata +# obj.errordata +# pem.errordata +# pkcs8.errordata +# rsa.errordata +# ssl.errordata +# x509.errordata +# x509v3.errordata +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +#) + +add_library( + err + + OBJECT + + err.c + err_data.c +) + +if(ENABLE_TESTS) +add_executable( + err_test + + err_test.cc + + $ +) + +target_link_libraries(err_test crypto) +add_dependencies(all_tests err_test) +endif() diff --git a/external/boringssl/crypto/err/asn1.errordata b/external/boringssl/crypto/err/asn1.errordata new file mode 100644 index 0000000000..c304b2caf5 --- /dev/null +++ b/external/boringssl/crypto/err/asn1.errordata @@ -0,0 +1,92 @@ +ASN1,100,ASN1_LENGTH_MISMATCH +ASN1,101,AUX_ERROR +ASN1,102,BAD_GET_ASN1_OBJECT_CALL +ASN1,103,BAD_OBJECT_HEADER +ASN1,104,BMPSTRING_IS_WRONG_LENGTH +ASN1,105,BN_LIB +ASN1,106,BOOLEAN_IS_WRONG_LENGTH +ASN1,107,BUFFER_TOO_SMALL +ASN1,108,CONTEXT_NOT_INITIALISED +ASN1,109,DECODE_ERROR +ASN1,110,DEPTH_EXCEEDED +ASN1,111,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED +ASN1,112,ENCODE_ERROR +ASN1,113,ERROR_GETTING_TIME +ASN1,114,EXPECTING_AN_ASN1_SEQUENCE +ASN1,115,EXPECTING_AN_INTEGER +ASN1,116,EXPECTING_AN_OBJECT +ASN1,117,EXPECTING_A_BOOLEAN +ASN1,118,EXPECTING_A_TIME +ASN1,119,EXPLICIT_LENGTH_MISMATCH +ASN1,120,EXPLICIT_TAG_NOT_CONSTRUCTED +ASN1,121,FIELD_MISSING +ASN1,122,FIRST_NUM_TOO_LARGE +ASN1,123,HEADER_TOO_LONG +ASN1,124,ILLEGAL_BITSTRING_FORMAT +ASN1,125,ILLEGAL_BOOLEAN +ASN1,126,ILLEGAL_CHARACTERS +ASN1,127,ILLEGAL_FORMAT +ASN1,128,ILLEGAL_HEX +ASN1,129,ILLEGAL_IMPLICIT_TAG +ASN1,130,ILLEGAL_INTEGER +ASN1,131,ILLEGAL_NESTED_TAGGING +ASN1,132,ILLEGAL_NULL +ASN1,133,ILLEGAL_NULL_VALUE +ASN1,134,ILLEGAL_OBJECT +ASN1,135,ILLEGAL_OPTIONAL_ANY +ASN1,136,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE +ASN1,137,ILLEGAL_TAGGED_ANY +ASN1,138,ILLEGAL_TIME_VALUE +ASN1,139,INTEGER_NOT_ASCII_FORMAT +ASN1,140,INTEGER_TOO_LARGE_FOR_LONG +ASN1,141,INVALID_BIT_STRING_BITS_LEFT +ASN1,142,INVALID_BMPSTRING_LENGTH +ASN1,143,INVALID_DIGIT +ASN1,144,INVALID_MODIFIER +ASN1,145,INVALID_NUMBER +ASN1,146,INVALID_OBJECT_ENCODING +ASN1,147,INVALID_SEPARATOR +ASN1,148,INVALID_TIME_FORMAT +ASN1,149,INVALID_UNIVERSALSTRING_LENGTH +ASN1,150,INVALID_UTF8STRING +ASN1,151,LIST_ERROR +ASN1,152,MISSING_ASN1_EOS +ASN1,153,MISSING_EOC +ASN1,154,MISSING_SECOND_NUMBER +ASN1,155,MISSING_VALUE +ASN1,156,MSTRING_NOT_UNIVERSAL +ASN1,157,MSTRING_WRONG_TAG +ASN1,158,NESTED_ASN1_ERROR +ASN1,159,NESTED_ASN1_STRING +ASN1,160,NON_HEX_CHARACTERS +ASN1,161,NOT_ASCII_FORMAT +ASN1,162,NOT_ENOUGH_DATA +ASN1,163,NO_MATCHING_CHOICE_TYPE +ASN1,164,NULL_IS_WRONG_LENGTH +ASN1,165,OBJECT_NOT_ASCII_FORMAT +ASN1,166,ODD_NUMBER_OF_CHARS +ASN1,167,SECOND_NUMBER_TOO_LARGE +ASN1,168,SEQUENCE_LENGTH_MISMATCH +ASN1,169,SEQUENCE_NOT_CONSTRUCTED +ASN1,170,SEQUENCE_OR_SET_NEEDS_CONFIG +ASN1,171,SHORT_LINE +ASN1,172,STREAMING_NOT_SUPPORTED +ASN1,173,STRING_TOO_LONG +ASN1,174,STRING_TOO_SHORT +ASN1,175,TAG_VALUE_TOO_HIGH +ASN1,176,TIME_NOT_ASCII_FORMAT +ASN1,177,TOO_LONG +ASN1,178,TYPE_NOT_CONSTRUCTED +ASN1,179,TYPE_NOT_PRIMITIVE +ASN1,180,UNEXPECTED_EOC +ASN1,181,UNIVERSALSTRING_IS_WRONG_LENGTH +ASN1,182,UNKNOWN_FORMAT +ASN1,183,UNKNOWN_MESSAGE_DIGEST_ALGORITHM +ASN1,184,UNKNOWN_SIGNATURE_ALGORITHM +ASN1,185,UNKNOWN_TAG +ASN1,186,UNSUPPORTED_ANY_DEFINED_BY_TYPE +ASN1,187,UNSUPPORTED_PUBLIC_KEY_TYPE +ASN1,188,UNSUPPORTED_TYPE +ASN1,189,WRONG_PUBLIC_KEY_TYPE +ASN1,190,WRONG_TAG +ASN1,191,WRONG_TYPE diff --git a/external/boringssl/crypto/err/bio.errordata b/external/boringssl/crypto/err/bio.errordata new file mode 100644 index 0000000000..94b3c9717e --- /dev/null +++ b/external/boringssl/crypto/err/bio.errordata @@ -0,0 +1,17 @@ +BIO,100,BAD_FOPEN_MODE +BIO,101,BROKEN_PIPE +BIO,102,CONNECT_ERROR +BIO,103,ERROR_SETTING_NBIO +BIO,104,INVALID_ARGUMENT +BIO,105,IN_USE +BIO,106,KEEPALIVE +BIO,107,NBIO_CONNECT_ERROR +BIO,108,NO_HOSTNAME_SPECIFIED +BIO,109,NO_PORT_SPECIFIED +BIO,110,NO_SUCH_FILE +BIO,111,NULL_PARAMETER +BIO,112,SYS_LIB +BIO,113,UNABLE_TO_CREATE_SOCKET +BIO,114,UNINITIALIZED +BIO,115,UNSUPPORTED_METHOD +BIO,116,WRITE_TO_READ_ONLY_BIO diff --git a/external/boringssl/crypto/err/bn.errordata b/external/boringssl/crypto/err/bn.errordata new file mode 100644 index 0000000000..76b63925d2 --- /dev/null +++ b/external/boringssl/crypto/err/bn.errordata @@ -0,0 +1,19 @@ +BN,100,ARG2_LT_ARG3 +BN,117,BAD_ENCODING +BN,101,BAD_RECIPROCAL +BN,102,BIGNUM_TOO_LONG +BN,103,BITS_TOO_SMALL +BN,104,CALLED_WITH_EVEN_MODULUS +BN,105,DIV_BY_ZERO +BN,118,ENCODE_ERROR +BN,106,EXPAND_ON_STATIC_BIGNUM_DATA +BN,107,INPUT_NOT_REDUCED +BN,108,INVALID_RANGE +BN,109,NEGATIVE_NUMBER +BN,110,NOT_A_SQUARE +BN,111,NOT_INITIALIZED +BN,112,NO_INVERSE +BN,113,PRIVATE_KEY_TOO_LARGE +BN,114,P_IS_NOT_PRIME +BN,115,TOO_MANY_ITERATIONS +BN,116,TOO_MANY_TEMPORARY_VARIABLES diff --git a/external/boringssl/crypto/err/cipher.errordata b/external/boringssl/crypto/err/cipher.errordata new file mode 100644 index 0000000000..103750558f --- /dev/null +++ b/external/boringssl/crypto/err/cipher.errordata @@ -0,0 +1,25 @@ +CIPHER,100,AES_KEY_SETUP_FAILED +CIPHER,101,BAD_DECRYPT +CIPHER,102,BAD_KEY_LENGTH +CIPHER,103,BUFFER_TOO_SMALL +CIPHER,104,CTRL_NOT_IMPLEMENTED +CIPHER,105,CTRL_OPERATION_NOT_IMPLEMENTED +CIPHER,106,DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH +CIPHER,107,INITIALIZATION_ERROR +CIPHER,108,INPUT_NOT_INITIALIZED +CIPHER,109,INVALID_AD_SIZE +CIPHER,110,INVALID_KEY_LENGTH +CIPHER,111,INVALID_NONCE_SIZE +CIPHER,112,INVALID_OPERATION +CIPHER,113,IV_TOO_LARGE +CIPHER,114,NO_CIPHER_SET +CIPHER,124,NO_DIRECTION_SET +CIPHER,115,OUTPUT_ALIASES_INPUT +CIPHER,116,TAG_TOO_LARGE +CIPHER,117,TOO_LARGE +CIPHER,118,UNSUPPORTED_AD_SIZE +CIPHER,119,UNSUPPORTED_INPUT_SIZE +CIPHER,120,UNSUPPORTED_KEY_SIZE +CIPHER,121,UNSUPPORTED_NONCE_SIZE +CIPHER,122,UNSUPPORTED_TAG_SIZE +CIPHER,123,WRONG_FINAL_BLOCK_LENGTH diff --git a/external/boringssl/crypto/err/conf.errordata b/external/boringssl/crypto/err/conf.errordata new file mode 100644 index 0000000000..651fabe10a --- /dev/null +++ b/external/boringssl/crypto/err/conf.errordata @@ -0,0 +1,6 @@ +CONF,100,LIST_CANNOT_BE_NULL +CONF,101,MISSING_CLOSE_SQUARE_BRACKET +CONF,102,MISSING_EQUAL_SIGN +CONF,103,NO_CLOSE_BRACE +CONF,104,UNABLE_TO_CREATE_NEW_SECTION +CONF,105,VARIABLE_HAS_NO_VALUE diff --git a/external/boringssl/crypto/err/dh.errordata b/external/boringssl/crypto/err/dh.errordata new file mode 100644 index 0000000000..9e1b87d850 --- /dev/null +++ b/external/boringssl/crypto/err/dh.errordata @@ -0,0 +1,6 @@ +DH,100,BAD_GENERATOR +DH,104,DECODE_ERROR +DH,105,ENCODE_ERROR +DH,101,INVALID_PUBKEY +DH,102,MODULUS_TOO_LARGE +DH,103,NO_PRIVATE_VALUE diff --git a/external/boringssl/crypto/err/digest.errordata b/external/boringssl/crypto/err/digest.errordata new file mode 100644 index 0000000000..411e778b84 --- /dev/null +++ b/external/boringssl/crypto/err/digest.errordata @@ -0,0 +1 @@ +DIGEST,100,INPUT_NOT_INITIALIZED diff --git a/external/boringssl/crypto/err/dsa.errordata b/external/boringssl/crypto/err/dsa.errordata new file mode 100644 index 0000000000..6f4bc138ab --- /dev/null +++ b/external/boringssl/crypto/err/dsa.errordata @@ -0,0 +1,7 @@ +DSA,100,BAD_Q_VALUE +DSA,104,BAD_VERSION +DSA,105,DECODE_ERROR +DSA,106,ENCODE_ERROR +DSA,101,MISSING_PARAMETERS +DSA,102,MODULUS_TOO_LARGE +DSA,103,NEED_NEW_SETUP_VALUES diff --git a/external/boringssl/crypto/err/ec.errordata b/external/boringssl/crypto/err/ec.errordata new file mode 100644 index 0000000000..d074afc967 --- /dev/null +++ b/external/boringssl/crypto/err/ec.errordata @@ -0,0 +1,31 @@ +EC,126,BIGNUM_OUT_OF_RANGE +EC,100,BUFFER_TOO_SMALL +EC,101,COORDINATES_OUT_OF_RANGE +EC,102,D2I_ECPKPARAMETERS_FAILURE +EC,128,DECODE_ERROR +EC,103,EC_GROUP_NEW_BY_NAME_FAILURE +EC,129,ENCODE_ERROR +EC,104,GROUP2PKPARAMETERS_FAILURE +EC,130,GROUP_MISMATCH +EC,105,I2D_ECPKPARAMETERS_FAILURE +EC,106,INCOMPATIBLE_OBJECTS +EC,107,INVALID_COMPRESSED_POINT +EC,108,INVALID_COMPRESSION_BIT +EC,109,INVALID_ENCODING +EC,110,INVALID_FIELD +EC,111,INVALID_FORM +EC,112,INVALID_GROUP_ORDER +EC,113,INVALID_PRIVATE_KEY +EC,114,MISSING_PARAMETERS +EC,115,MISSING_PRIVATE_KEY +EC,116,NON_NAMED_CURVE +EC,117,NOT_INITIALIZED +EC,118,PKPARAMETERS2GROUP_FAILURE +EC,119,POINT_AT_INFINITY +EC,120,POINT_IS_NOT_ON_CURVE +EC,121,SLOT_FULL +EC,122,UNDEFINED_GENERATOR +EC,123,UNKNOWN_GROUP +EC,124,UNKNOWN_ORDER +EC,127,WRONG_CURVE_PARAMETERS +EC,125,WRONG_ORDER diff --git a/external/boringssl/crypto/err/ecdh.errordata b/external/boringssl/crypto/err/ecdh.errordata new file mode 100644 index 0000000000..f714c3049d --- /dev/null +++ b/external/boringssl/crypto/err/ecdh.errordata @@ -0,0 +1,3 @@ +ECDH,100,KDF_FAILED +ECDH,101,NO_PRIVATE_VALUE +ECDH,102,POINT_ARITHMETIC_FAILURE diff --git a/external/boringssl/crypto/err/ecdsa.errordata b/external/boringssl/crypto/err/ecdsa.errordata new file mode 100644 index 0000000000..58ba591fab --- /dev/null +++ b/external/boringssl/crypto/err/ecdsa.errordata @@ -0,0 +1,6 @@ +ECDSA,100,BAD_SIGNATURE +ECDSA,105,ENCODE_ERROR +ECDSA,101,MISSING_PARAMETERS +ECDSA,102,NEED_NEW_SETUP_VALUES +ECDSA,103,NOT_IMPLEMENTED +ECDSA,104,RANDOM_NUMBER_GENERATION_FAILED diff --git a/external/boringssl/crypto/err/engine.errordata b/external/boringssl/crypto/err/engine.errordata new file mode 100644 index 0000000000..edbd7b97b9 --- /dev/null +++ b/external/boringssl/crypto/err/engine.errordata @@ -0,0 +1 @@ +ENGINE,100,OPERATION_NOT_SUPPORTED diff --git a/external/boringssl/crypto/err/err.c b/external/boringssl/crypto/err/err.c new file mode 100644 index 0000000000..48d631f4cf --- /dev/null +++ b/external/boringssl/crypto/err/err.c @@ -0,0 +1,756 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include + +#include "../internal.h" + + +extern const uint32_t kOpenSSLReasonValues[]; +extern const size_t kOpenSSLReasonValuesLen; +extern const char kOpenSSLReasonStringData[]; + +/* err_clear_data frees the optional |data| member of the given error. */ +static void err_clear_data(struct err_error_st *error) { + if ((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)); +} + +/* global_next_library contains the next custom library value to return. */ +static int global_next_library = ERR_NUM_LIBS; + +/* global_next_library_mutex protects |global_next_library| from concurrent + * updates. */ +static struct CRYPTO_STATIC_MUTEX global_next_library_mutex = + CRYPTO_STATIC_MUTEX_INIT; + +static void err_state_free(void *statep) { + ERR_STATE *state = statep; + + if (state == NULL) { + return; + } + + unsigned i; + for (i = 0; i < ERR_NUM_ERRORS; i++) { + err_clear(&state->errors[i]); + } + OPENSSL_free(state->to_free); + OPENSSL_free(state); +} + +/* err_get_state gets the ERR_STATE object for the current thread. */ +static ERR_STATE *err_get_state(void) { + ERR_STATE *state = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_ERR); + if (state == NULL) { + state = OPENSSL_malloc(sizeof(ERR_STATE)); + if (state == NULL) { + return NULL; + } + memset(state, 0, sizeof(ERR_STATE)); + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_ERR, state, + err_state_free)) { + return NULL; + } + } + + return 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) { + 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 /* inc */, 0 /* bottom */, NULL, NULL, NULL, NULL); +} + +uint32_t ERR_get_error_line(const char **file, int *line) { + return get_error_values(1 /* inc */, 0 /* bottom */, 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 /* inc */, 0 /* bottom */, file, line, data, flags); +} + +uint32_t ERR_peek_error(void) { + return get_error_values(0 /* peek */, 0 /* bottom */, NULL, NULL, NULL, NULL); +} + +uint32_t ERR_peek_error_line(const char **file, int *line) { + return get_error_values(0 /* peek */, 0 /* bottom */, 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 /* peek */, 0 /* bottom */, file, line, data, + flags); +} + +uint32_t ERR_peek_last_error(void) { + return get_error_values(0 /* peek */, 1 /* top */, NULL, NULL, NULL, NULL); +} + +uint32_t ERR_peek_last_error_line(const char **file, int *line) { + return get_error_values(0 /* peek */, 1 /* top */, 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 /* peek */, 1 /* top */, 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]); + } + OPENSSL_free(state->to_free); + state->to_free = NULL; + + state->top = state->bottom = 0; +} + +void ERR_remove_thread_state(const CRYPTO_THREADID *tid) { + if (tid != NULL) { + assert(0); + return; + } + + ERR_clear_error(); +} + +int ERR_get_next_error_library(void) { + int ret; + + CRYPTO_STATIC_MUTEX_lock_write(&global_next_library_mutex); + ret = global_next_library++; + CRYPTO_STATIC_MUTEX_unlock_write(&global_next_library_mutex); + + return ret; +} + +void ERR_remove_state(unsigned long pid) { + ERR_clear_error(); +} + +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], reason_buf[64]; + const char *lib_str, *reason_str; + unsigned lib, reason; + + if (len == 0) { + return; + } + + lib = ERR_GET_LIB(packed_error); + reason = ERR_GET_REASON(packed_error); + + lib_str = ERR_lib_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 (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:OPENSSL_internal:%s", + packed_error, lib_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_string_cmp is a compare function for searching error values with +// |bsearch| in |err_string_lookup|. +static int err_string_cmp(const void *a, const void *b) { + const uint32_t a_key = *((const uint32_t*) a) >> 15; + const uint32_t b_key = *((const uint32_t*) b) >> 15; + + if (a_key < b_key) { + return -1; + } else if (a_key > b_key) { + return 1; + } else { + return 0; + } +} + +/* err_string_lookup looks up the string associated with |lib| and |key| in + * |values| and |string_data|. It returns the string or NULL if not found. */ +static const char *err_string_lookup(uint32_t lib, uint32_t key, + const uint32_t *values, + size_t num_values, + const char *string_data) { + /* |values| points to data in err_data.h, which is generated by + * err_data_generate.go. It's an array of uint32_t values. Each value has the + * following structure: + * | lib | key | offset | + * |6 bits| 11 bits | 15 bits | + * + * The |lib| value is a library identifier: one of the |ERR_LIB_*| values. + * The |key| is a reason code, depending on the context. + * The |offset| is the number of bytes from the start of |string_data| where + * the (NUL terminated) string for this value can be found. + * + * Values are sorted based on treating the |lib| and |key| part as an + * unsigned integer. */ + if (lib >= (1 << 6) || key >= (1 << 11)) { + return NULL; + } + uint32_t search_key = lib << 26 | key << 15; + const uint32_t *result = bsearch(&search_key, values, num_values, + sizeof(uint32_t), err_string_cmp); + if (result == NULL) { + return NULL; + } + + return &string_data[(*result) & 0x7fff]; +} + +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 */ + "HKDF functions", /* ERR_LIB_HKDF */ + "User defined functions", /* ERR_LIB_USER */ +}; + +const char *ERR_lib_error_string(uint32_t packed_error) { + const uint32_t lib = ERR_GET_LIB(packed_error); + + if (lib >= ERR_NUM_LIBS) { + return NULL; + } + return kLibraryNames[lib]; +} + +const char *ERR_func_error_string(uint32_t packed_error) { + return "OPENSSL_internal"; +} + +const char *ERR_reason_error_string(uint32_t packed_error) { + const uint32_t lib = ERR_GET_LIB(packed_error); + const uint32_t reason = ERR_GET_REASON(packed_error); + + if (lib == ERR_LIB_SYS) { + if (reason < 127) { + return strerror(reason); + } + return NULL; + } + + if (reason < ERR_NUM_LIBS) { + return kLibraryNames[reason]; + } + + if (reason < 100) { + switch (reason) { + case ERR_R_MALLOC_FAILURE: + return "malloc failure"; + case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED: + return "function should not have been called"; + case ERR_R_PASSED_NULL_PARAMETER: + return "passed a null parameter"; + case ERR_R_INTERNAL_ERROR: + return "internal error"; + case ERR_R_OVERFLOW: + return "overflow"; + default: + return NULL; + } + } + + return err_string_lookup(lib, reason, kOpenSSLReasonValues, + kOpenSSLReasonValuesLen, kOpenSSLReasonStringData); +} + +void ERR_print_errors_cb(ERR_print_errors_callback_t callback, void *ctx) { + char buf[ERR_ERROR_STRING_BUF_LEN]; + char buf2[1024]; + const char *file, *data; + int line, flags; + uint32_t packed_error; + + /* thread_hash is the least-significant bits of the |ERR_STATE| pointer value + * for this thread. */ + const unsigned long thread_hash = (uintptr_t) err_get_state(); + + 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; + } + } +} + +static int print_errors_to_file(const char* msg, size_t msg_len, void* ctx) { + assert(msg[msg_len] == '\0'); + FILE* fp = ctx; + int res = fputs(msg, fp); + return res < 0 ? 0 : 1; +} + +void ERR_print_errors_fp(FILE *file) { + ERR_print_errors_cb(print_errors_to_file, file); +} + +/* 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 unused, 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(OPENSSL_WINDOWS) + 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, 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; +} + +void ERR_load_crypto_strings(void) {} + +void ERR_free_strings(void) {} + +void ERR_load_BIO_strings(void) {} + +void ERR_load_ERR_strings(void) {} diff --git a/external/boringssl/crypto/err/err_data.c b/external/boringssl/crypto/err/err_data.c new file mode 100644 index 0000000000..d4cc08bd99 --- /dev/null +++ b/external/boringssl/crypto/err/err_data.c @@ -0,0 +1,1258 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + /* This file was generated by err_data_generate.go. */ + +#include +#include +#include + + +OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); +OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); +OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); +OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); +OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); +OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); +OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); +OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); +OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); +OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); +OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); +OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); +OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); +OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); +OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); +OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); +OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); + +const uint32_t kOpenSSLReasonValues[] = { + 0xc3207ab, + 0xc3287c5, + 0xc3307d4, + 0xc3387e4, + 0xc3407f3, + 0xc34880c, + 0xc350818, + 0xc358835, + 0xc360847, + 0xc368855, + 0xc370865, + 0xc378872, + 0xc380882, + 0xc38888d, + 0xc3908a3, + 0xc3988b2, + 0xc3a08c6, + 0xc3a87b8, + 0xc3b00b0, + 0x10321484, + 0x10329490, + 0x103314a9, + 0x103394bc, + 0x10340ded, + 0x103494cf, + 0x103514e4, + 0x10359516, + 0x1036152f, + 0x10369544, + 0x10371562, + 0x10379571, + 0x1038158d, + 0x103895a8, + 0x103915b7, + 0x103995d3, + 0x103a15ee, + 0x103a9605, + 0x103b1616, + 0x103b962a, + 0x103c1649, + 0x103c9658, + 0x103d166f, + 0x103d9682, + 0x103e0b5d, + 0x103e96b3, + 0x103f16c6, + 0x103f96e0, + 0x104016f0, + 0x10409704, + 0x1041171a, + 0x10419732, + 0x10421747, + 0x1042975b, + 0x1043176d, + 0x104385c1, + 0x104408b2, + 0x10449782, + 0x10451799, + 0x104597ae, + 0x104617bc, + 0x10469695, + 0x104714f7, + 0x104787b8, + 0x104800b0, + 0x10488b8c, + 0x14320b40, + 0x14328b4e, + 0x14330b5d, + 0x14338b6f, + 0x18320083, + 0x18328e53, + 0x18340e81, + 0x18348e95, + 0x18358ecc, + 0x18368ef9, + 0x18370f0c, + 0x18378f20, + 0x18380f44, + 0x18388f52, + 0x18390f68, + 0x18398f7c, + 0x183a0f8c, + 0x183b0f9c, + 0x183b8fb1, + 0x183c8fdc, + 0x183d0ff0, + 0x183d9000, + 0x183e0b98, + 0x183e900d, + 0x183f101f, + 0x183f902a, + 0x1840103a, + 0x1840904b, + 0x1841105c, + 0x1841906e, + 0x18421097, + 0x184290c9, + 0x184310d8, + 0x18451141, + 0x18459157, + 0x18461172, + 0x18468ee4, + 0x184709ca, + 0x18478094, + 0x18480fc8, + 0x1848910d, + 0x18490e69, + 0x18498eaa, + 0x184a11a8, + 0x184a9125, + 0x184b10ec, + 0x184b8e43, + 0x184c10b0, + 0x184c865c, + 0x184d118d, + 0x184d80b0, + 0x203211cf, + 0x243211db, + 0x243288f8, + 0x243311ed, + 0x243391fa, + 0x24341207, + 0x24349219, + 0x24351228, + 0x24359245, + 0x24361252, + 0x24369260, + 0x2437126e, + 0x2437927c, + 0x24381285, + 0x24389292, + 0x243912a5, + 0x28320b80, + 0x28328b98, + 0x28330b5d, + 0x28338bab, + 0x28340b8c, + 0x28348094, + 0x283500b0, + 0x2c32281d, + 0x2c32a82b, + 0x2c33283d, + 0x2c33a84f, + 0x2c342863, + 0x2c34a875, + 0x2c352890, + 0x2c35a8a2, + 0x2c3628b5, + 0x2c3682f3, + 0x2c3728c2, + 0x2c37a8d4, + 0x2c3828e7, + 0x2c38a8f5, + 0x2c392905, + 0x2c39a917, + 0x2c3a292b, + 0x2c3aa93c, + 0x2c3b1365, + 0x2c3ba94d, + 0x2c3c2961, + 0x2c3ca977, + 0x2c3d2990, + 0x2c3da9be, + 0x2c3e29cc, + 0x2c3ea9e4, + 0x2c3f29fc, + 0x2c3faa09, + 0x2c402a2c, + 0x2c40aa4b, + 0x2c4111cf, + 0x2c41aa5c, + 0x2c422a6f, + 0x2c429141, + 0x2c432a80, + 0x2c438693, + 0x2c4429ad, + 0x30320000, + 0x30328015, + 0x3033001f, + 0x30338038, + 0x3034004a, + 0x30348064, + 0x3035006b, + 0x30358083, + 0x30360094, + 0x303680a1, + 0x303700b0, + 0x303780bd, + 0x303800d0, + 0x303880eb, + 0x30390100, + 0x30398114, + 0x303a0128, + 0x303a8139, + 0x303b0152, + 0x303b816f, + 0x303c017d, + 0x303c8191, + 0x303d01a1, + 0x303d81ba, + 0x303e01ca, + 0x303e81dd, + 0x303f01ec, + 0x303f81f8, + 0x3040020d, + 0x3040821d, + 0x30410234, + 0x30418241, + 0x30420254, + 0x30428263, + 0x30430278, + 0x30438299, + 0x304402ac, + 0x304482bf, + 0x304502d8, + 0x304582f3, + 0x30460310, + 0x30468329, + 0x30470337, + 0x30478348, + 0x30480357, + 0x3048836f, + 0x30490381, + 0x30498395, + 0x304a03b4, + 0x304a83c7, + 0x304b03d2, + 0x304b83e3, + 0x304c03ef, + 0x304c8405, + 0x304d0413, + 0x304d8429, + 0x304e043b, + 0x304e844d, + 0x304f0460, + 0x304f8473, + 0x30500484, + 0x30508494, + 0x305104ac, + 0x305184c1, + 0x305204d9, + 0x305284ed, + 0x30530505, + 0x3053851e, + 0x30540537, + 0x30548554, + 0x3055055f, + 0x30558577, + 0x30560587, + 0x30568598, + 0x305705ab, + 0x305785c1, + 0x305805ca, + 0x305885df, + 0x305905f2, + 0x30598601, + 0x305a0621, + 0x305a8630, + 0x305b063c, + 0x305b865c, + 0x305c0678, + 0x305c8689, + 0x305d0693, + 0x34320aba, + 0x34328ace, + 0x34330aeb, + 0x34338afe, + 0x34340b0d, + 0x34348b2a, + 0x3c320083, + 0x3c328bd5, + 0x3c330bee, + 0x3c338c09, + 0x3c340c26, + 0x3c348c50, + 0x3c350c6b, + 0x3c358c80, + 0x3c360c99, + 0x3c368cb1, + 0x3c370cc2, + 0x3c378cd0, + 0x3c380cdd, + 0x3c388cf1, + 0x3c390b98, + 0x3c398d05, + 0x3c3a0d19, + 0x3c3a8872, + 0x3c3b0d29, + 0x3c3b8d44, + 0x3c3c0d56, + 0x3c3c8d6c, + 0x3c3d0d76, + 0x3c3d8d8a, + 0x3c3e0d98, + 0x3c3e8dbd, + 0x3c3f0bc1, + 0x3c3f8da6, + 0x3c400094, + 0x3c4080b0, + 0x3c410c41, + 0x403217d3, + 0x403297e9, + 0x40331817, + 0x40339821, + 0x40341838, + 0x40349856, + 0x40351866, + 0x40359878, + 0x40361885, + 0x40369891, + 0x403718a6, + 0x403798b8, + 0x403818c3, + 0x403898d5, + 0x40390ded, + 0x403998e5, + 0x403a18f8, + 0x403a9919, + 0x403b192a, + 0x403b993a, + 0x403c0064, + 0x403c8083, + 0x403d1946, + 0x403d995c, + 0x403e196b, + 0x403e997e, + 0x403f1998, + 0x403f99a6, + 0x404019bb, + 0x404099cf, + 0x404119ec, + 0x40419a07, + 0x40421a20, + 0x40429a33, + 0x40431a47, + 0x40439a5f, + 0x40441a76, + 0x40448094, + 0x40451a8b, + 0x40459a9d, + 0x40461ac1, + 0x40469ae1, + 0x40471aef, + 0x40479b03, + 0x40481b18, + 0x40489b31, + 0x40491b48, + 0x40499b62, + 0x404a1b79, + 0x404a9b97, + 0x404b1baf, + 0x404b9bc6, + 0x404c1bdc, + 0x404c9bee, + 0x404d1c0f, + 0x404d9c31, + 0x404e1c45, + 0x404e9c52, + 0x404f1c69, + 0x404f9c79, + 0x40501c89, + 0x40509c9d, + 0x40511cb8, + 0x40519cc8, + 0x40521cdf, + 0x40529cf1, + 0x40531d09, + 0x40539d1c, + 0x40541d31, + 0x40549d54, + 0x40551d62, + 0x40559d7f, + 0x40561d8c, + 0x40569da5, + 0x40571dbd, + 0x40579dd0, + 0x40581de5, + 0x40589df7, + 0x40591e07, + 0x40599e20, + 0x405a1e34, + 0x405a9e44, + 0x405b1e5c, + 0x405b9e6d, + 0x405c1e80, + 0x405c9e91, + 0x405d1e9e, + 0x405d9eb5, + 0x405e1ed5, + 0x405e8a08, + 0x405f1ef6, + 0x405f9f03, + 0x40601f11, + 0x40609f33, + 0x40611f5b, + 0x40619f70, + 0x40621f87, + 0x40629f98, + 0x40631fa9, + 0x40639fbe, + 0x40641fd5, + 0x40649fe6, + 0x40652001, + 0x4065a018, + 0x40662030, + 0x4066a05a, + 0x40672085, + 0x4067a0a6, + 0x406820b9, + 0x4068a0da, + 0x406920f5, + 0x4069a123, + 0x406a2144, + 0x406aa164, + 0x406b22ec, + 0x406ba30f, + 0x406c2325, + 0x406ca551, + 0x406d2580, + 0x406da5a8, + 0x406e25c1, + 0x406ea5d9, + 0x406f25f8, + 0x406fa60d, + 0x40702620, + 0x4070a63d, + 0x40710773, + 0x4071a64f, + 0x40722662, + 0x4072a67b, + 0x40732693, + 0x407390c9, + 0x407426a7, + 0x4074a6c1, + 0x407526d2, + 0x4075a6e6, + 0x407626f4, + 0x40769292, + 0x40772719, + 0x4077a73b, + 0x40782756, + 0x4078a76b, + 0x40792782, + 0x4079a798, + 0x407a27a4, + 0x407aa7b7, + 0x407b27cc, + 0x407ba7de, + 0x407c27f3, + 0x407ca7fc, + 0x41f42217, + 0x41f922a9, + 0x41fe219c, + 0x41fea378, + 0x41ff2469, + 0x42032230, + 0x42082252, + 0x4208a28e, + 0x42092180, + 0x4209a2c8, + 0x420a21d7, + 0x420aa1b7, + 0x420b21f7, + 0x420ba270, + 0x420c2485, + 0x420ca345, + 0x420d235f, + 0x420da396, + 0x421223b0, + 0x4217244c, + 0x4217a3f2, + 0x421c2414, + 0x421f23cf, + 0x4221249c, + 0x4226242f, + 0x422b2535, + 0x422ba4fe, + 0x422c251d, + 0x422ca4d8, + 0x422d24b7, + 0x4432069e, + 0x443286ad, + 0x443306b9, + 0x443386c7, + 0x443406da, + 0x443486eb, + 0x443506f2, + 0x443586fc, + 0x4436070f, + 0x44368725, + 0x44370737, + 0x44378744, + 0x44380753, + 0x4438875b, + 0x44390773, + 0x44398781, + 0x443a0794, + 0x4c3212bc, + 0x4c3292cc, + 0x4c3312df, + 0x4c3392ff, + 0x4c340094, + 0x4c3480b0, + 0x4c35130b, + 0x4c359319, + 0x4c361335, + 0x4c369348, + 0x4c371357, + 0x4c379365, + 0x4c38137a, + 0x4c389386, + 0x4c3913a6, + 0x4c3993d0, + 0x4c3a13e9, + 0x4c3a9402, + 0x4c3b05c1, + 0x4c3b941b, + 0x4c3c142d, + 0x4c3c943c, + 0x4c3d10c9, + 0x4c3d9455, + 0x4c3e1462, + 0x50322a92, + 0x5032aaa1, + 0x50332aac, + 0x5033aabc, + 0x50342ad5, + 0x5034aaef, + 0x50352afd, + 0x5035ab13, + 0x50362b25, + 0x5036ab3b, + 0x50372b54, + 0x5037ab67, + 0x50382b7f, + 0x5038ab90, + 0x50392ba5, + 0x5039abb9, + 0x503a2bd9, + 0x503aabef, + 0x503b2c07, + 0x503bac19, + 0x503c2c35, + 0x503cac4c, + 0x503d2c65, + 0x503dac7b, + 0x503e2c88, + 0x503eac9e, + 0x503f2cb0, + 0x503f8348, + 0x50402cc3, + 0x5040acd3, + 0x50412ced, + 0x5041acfc, + 0x50422d16, + 0x5042ad33, + 0x50432d43, + 0x5043ad53, + 0x50442d62, + 0x50448405, + 0x50452d76, + 0x5045ad94, + 0x50462da7, + 0x5046adbd, + 0x50472dcf, + 0x5047ade4, + 0x50482e0a, + 0x5048ae18, + 0x50492e2b, + 0x5049ae40, + 0x504a2e56, + 0x504aae66, + 0x504b2e86, + 0x504bae99, + 0x504c2ebc, + 0x504caeea, + 0x504d2efc, + 0x504daf19, + 0x504e2f34, + 0x504eaf50, + 0x504f2f62, + 0x504faf79, + 0x50502f88, + 0x50508678, + 0x50512f9b, + 0x58320e2b, + 0x68320ded, + 0x68328b98, + 0x68330bab, + 0x68338dfb, + 0x68340e0b, + 0x683480b0, + 0x6c320dc9, + 0x6c328b6f, + 0x6c330dd4, + 0x7432097e, + 0x783208e3, + 0x783288f8, + 0x78330904, + 0x78338083, + 0x78340913, + 0x78348928, + 0x78350947, + 0x78358969, + 0x7836097e, + 0x78368994, + 0x783709a4, + 0x783789b7, + 0x783809ca, + 0x783889dc, + 0x783909e9, + 0x78398a08, + 0x783a0a1d, + 0x783a8a2b, + 0x783b0a35, + 0x783b8a49, + 0x783c0a60, + 0x783c8a75, + 0x783d0a8c, + 0x783d8aa1, + 0x783e09f7, + 0x7c3211be, +}; + +const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); + +const char kOpenSSLReasonStringData[] = + "ASN1_LENGTH_MISMATCH\0" + "AUX_ERROR\0" + "BAD_GET_ASN1_OBJECT_CALL\0" + "BAD_OBJECT_HEADER\0" + "BMPSTRING_IS_WRONG_LENGTH\0" + "BN_LIB\0" + "BOOLEAN_IS_WRONG_LENGTH\0" + "BUFFER_TOO_SMALL\0" + "DECODE_ERROR\0" + "DEPTH_EXCEEDED\0" + "ENCODE_ERROR\0" + "ERROR_GETTING_TIME\0" + "EXPECTING_AN_ASN1_SEQUENCE\0" + "EXPECTING_AN_INTEGER\0" + "EXPECTING_AN_OBJECT\0" + "EXPECTING_A_BOOLEAN\0" + "EXPECTING_A_TIME\0" + "EXPLICIT_LENGTH_MISMATCH\0" + "EXPLICIT_TAG_NOT_CONSTRUCTED\0" + "FIELD_MISSING\0" + "FIRST_NUM_TOO_LARGE\0" + "HEADER_TOO_LONG\0" + "ILLEGAL_BITSTRING_FORMAT\0" + "ILLEGAL_BOOLEAN\0" + "ILLEGAL_CHARACTERS\0" + "ILLEGAL_FORMAT\0" + "ILLEGAL_HEX\0" + "ILLEGAL_IMPLICIT_TAG\0" + "ILLEGAL_INTEGER\0" + "ILLEGAL_NESTED_TAGGING\0" + "ILLEGAL_NULL\0" + "ILLEGAL_NULL_VALUE\0" + "ILLEGAL_OBJECT\0" + "ILLEGAL_OPTIONAL_ANY\0" + "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\0" + "ILLEGAL_TAGGED_ANY\0" + "ILLEGAL_TIME_VALUE\0" + "INTEGER_NOT_ASCII_FORMAT\0" + "INTEGER_TOO_LARGE_FOR_LONG\0" + "INVALID_BIT_STRING_BITS_LEFT\0" + "INVALID_BMPSTRING_LENGTH\0" + "INVALID_DIGIT\0" + "INVALID_MODIFIER\0" + "INVALID_NUMBER\0" + "INVALID_OBJECT_ENCODING\0" + "INVALID_SEPARATOR\0" + "INVALID_TIME_FORMAT\0" + "INVALID_UNIVERSALSTRING_LENGTH\0" + "INVALID_UTF8STRING\0" + "LIST_ERROR\0" + "MISSING_ASN1_EOS\0" + "MISSING_EOC\0" + "MISSING_SECOND_NUMBER\0" + "MISSING_VALUE\0" + "MSTRING_NOT_UNIVERSAL\0" + "MSTRING_WRONG_TAG\0" + "NESTED_ASN1_ERROR\0" + "NESTED_ASN1_STRING\0" + "NON_HEX_CHARACTERS\0" + "NOT_ASCII_FORMAT\0" + "NOT_ENOUGH_DATA\0" + "NO_MATCHING_CHOICE_TYPE\0" + "NULL_IS_WRONG_LENGTH\0" + "OBJECT_NOT_ASCII_FORMAT\0" + "ODD_NUMBER_OF_CHARS\0" + "SECOND_NUMBER_TOO_LARGE\0" + "SEQUENCE_LENGTH_MISMATCH\0" + "SEQUENCE_NOT_CONSTRUCTED\0" + "SEQUENCE_OR_SET_NEEDS_CONFIG\0" + "SHORT_LINE\0" + "STREAMING_NOT_SUPPORTED\0" + "STRING_TOO_LONG\0" + "STRING_TOO_SHORT\0" + "TAG_VALUE_TOO_HIGH\0" + "TIME_NOT_ASCII_FORMAT\0" + "TOO_LONG\0" + "TYPE_NOT_CONSTRUCTED\0" + "TYPE_NOT_PRIMITIVE\0" + "UNEXPECTED_EOC\0" + "UNIVERSALSTRING_IS_WRONG_LENGTH\0" + "UNKNOWN_FORMAT\0" + "UNKNOWN_TAG\0" + "UNSUPPORTED_ANY_DEFINED_BY_TYPE\0" + "UNSUPPORTED_PUBLIC_KEY_TYPE\0" + "UNSUPPORTED_TYPE\0" + "WRONG_TAG\0" + "WRONG_TYPE\0" + "BAD_FOPEN_MODE\0" + "BROKEN_PIPE\0" + "CONNECT_ERROR\0" + "ERROR_SETTING_NBIO\0" + "INVALID_ARGUMENT\0" + "IN_USE\0" + "KEEPALIVE\0" + "NBIO_CONNECT_ERROR\0" + "NO_HOSTNAME_SPECIFIED\0" + "NO_PORT_SPECIFIED\0" + "NO_SUCH_FILE\0" + "NULL_PARAMETER\0" + "SYS_LIB\0" + "UNABLE_TO_CREATE_SOCKET\0" + "UNINITIALIZED\0" + "UNSUPPORTED_METHOD\0" + "WRITE_TO_READ_ONLY_BIO\0" + "ARG2_LT_ARG3\0" + "BAD_ENCODING\0" + "BAD_RECIPROCAL\0" + "BIGNUM_TOO_LONG\0" + "BITS_TOO_SMALL\0" + "CALLED_WITH_EVEN_MODULUS\0" + "DIV_BY_ZERO\0" + "EXPAND_ON_STATIC_BIGNUM_DATA\0" + "INPUT_NOT_REDUCED\0" + "INVALID_RANGE\0" + "NEGATIVE_NUMBER\0" + "NOT_A_SQUARE\0" + "NOT_INITIALIZED\0" + "NO_INVERSE\0" + "PRIVATE_KEY_TOO_LARGE\0" + "P_IS_NOT_PRIME\0" + "TOO_MANY_ITERATIONS\0" + "TOO_MANY_TEMPORARY_VARIABLES\0" + "AES_KEY_SETUP_FAILED\0" + "BAD_DECRYPT\0" + "BAD_KEY_LENGTH\0" + "CTRL_NOT_IMPLEMENTED\0" + "CTRL_OPERATION_NOT_IMPLEMENTED\0" + "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\0" + "INITIALIZATION_ERROR\0" + "INPUT_NOT_INITIALIZED\0" + "INVALID_AD_SIZE\0" + "INVALID_KEY_LENGTH\0" + "INVALID_NONCE_SIZE\0" + "INVALID_OPERATION\0" + "IV_TOO_LARGE\0" + "NO_CIPHER_SET\0" + "NO_DIRECTION_SET\0" + "OUTPUT_ALIASES_INPUT\0" + "TAG_TOO_LARGE\0" + "TOO_LARGE\0" + "UNSUPPORTED_AD_SIZE\0" + "UNSUPPORTED_INPUT_SIZE\0" + "UNSUPPORTED_KEY_SIZE\0" + "UNSUPPORTED_NONCE_SIZE\0" + "UNSUPPORTED_TAG_SIZE\0" + "WRONG_FINAL_BLOCK_LENGTH\0" + "LIST_CANNOT_BE_NULL\0" + "MISSING_CLOSE_SQUARE_BRACKET\0" + "MISSING_EQUAL_SIGN\0" + "NO_CLOSE_BRACE\0" + "UNABLE_TO_CREATE_NEW_SECTION\0" + "VARIABLE_HAS_NO_VALUE\0" + "BAD_GENERATOR\0" + "INVALID_PUBKEY\0" + "MODULUS_TOO_LARGE\0" + "NO_PRIVATE_VALUE\0" + "BAD_Q_VALUE\0" + "BAD_VERSION\0" + "MISSING_PARAMETERS\0" + "NEED_NEW_SETUP_VALUES\0" + "BIGNUM_OUT_OF_RANGE\0" + "COORDINATES_OUT_OF_RANGE\0" + "D2I_ECPKPARAMETERS_FAILURE\0" + "EC_GROUP_NEW_BY_NAME_FAILURE\0" + "GROUP2PKPARAMETERS_FAILURE\0" + "GROUP_MISMATCH\0" + "I2D_ECPKPARAMETERS_FAILURE\0" + "INCOMPATIBLE_OBJECTS\0" + "INVALID_COMPRESSED_POINT\0" + "INVALID_COMPRESSION_BIT\0" + "INVALID_ENCODING\0" + "INVALID_FIELD\0" + "INVALID_FORM\0" + "INVALID_GROUP_ORDER\0" + "INVALID_PRIVATE_KEY\0" + "MISSING_PRIVATE_KEY\0" + "NON_NAMED_CURVE\0" + "PKPARAMETERS2GROUP_FAILURE\0" + "POINT_AT_INFINITY\0" + "POINT_IS_NOT_ON_CURVE\0" + "SLOT_FULL\0" + "UNDEFINED_GENERATOR\0" + "UNKNOWN_GROUP\0" + "UNKNOWN_ORDER\0" + "WRONG_CURVE_PARAMETERS\0" + "WRONG_ORDER\0" + "KDF_FAILED\0" + "POINT_ARITHMETIC_FAILURE\0" + "BAD_SIGNATURE\0" + "NOT_IMPLEMENTED\0" + "RANDOM_NUMBER_GENERATION_FAILED\0" + "OPERATION_NOT_SUPPORTED\0" + "BN_DECODE_ERROR\0" + "COMMAND_NOT_SUPPORTED\0" + "CONTEXT_NOT_INITIALISED\0" + "DIFFERENT_KEY_TYPES\0" + "DIFFERENT_PARAMETERS\0" + "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\0" + "EXPECTING_AN_EC_KEY_KEY\0" + "EXPECTING_AN_RSA_KEY\0" + "EXPECTING_A_DH_KEY\0" + "EXPECTING_A_DSA_KEY\0" + "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0" + "INVALID_CURVE\0" + "INVALID_DIGEST_LENGTH\0" + "INVALID_DIGEST_TYPE\0" + "INVALID_KEYBITS\0" + "INVALID_MGF1_MD\0" + "INVALID_PADDING_MODE\0" + "INVALID_PSS_PARAMETERS\0" + "INVALID_PSS_SALTLEN\0" + "INVALID_SALT_LENGTH\0" + "INVALID_TRAILER\0" + "KEYS_NOT_SET\0" + "NO_DEFAULT_DIGEST\0" + "NO_KEY_SET\0" + "NO_MDC2_SUPPORT\0" + "NO_NID_FOR_CURVE\0" + "NO_OPERATION_SET\0" + "NO_PARAMETERS_SET\0" + "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0" + "OPERATON_NOT_INITIALIZED\0" + "PARAMETER_ENCODING_ERROR\0" + "UNKNOWN_DIGEST\0" + "UNKNOWN_MASK_DIGEST\0" + "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0" + "UNKNOWN_PUBLIC_KEY_TYPE\0" + "UNKNOWN_SIGNATURE_ALGORITHM\0" + "UNSUPPORTED_ALGORITHM\0" + "UNSUPPORTED_MASK_ALGORITHM\0" + "UNSUPPORTED_MASK_PARAMETER\0" + "UNSUPPORTED_SIGNATURE_TYPE\0" + "WRONG_PUBLIC_KEY_TYPE\0" + "OUTPUT_TOO_LARGE\0" + "UNKNOWN_NID\0" + "BAD_BASE64_DECODE\0" + "BAD_END_LINE\0" + "BAD_IV_CHARS\0" + "BAD_PASSWORD_READ\0" + "CIPHER_IS_NULL\0" + "ERROR_CONVERTING_PRIVATE_KEY\0" + "NOT_DEK_INFO\0" + "NOT_ENCRYPTED\0" + "NOT_PROC_TYPE\0" + "NO_START_LINE\0" + "READ_KEY\0" + "SHORT_HEADER\0" + "UNSUPPORTED_CIPHER\0" + "UNSUPPORTED_ENCRYPTION\0" + "BAD_PKCS12_DATA\0" + "BAD_PKCS12_VERSION\0" + "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0" + "CRYPT_ERROR\0" + "ENCRYPT_ERROR\0" + "ERROR_SETTING_CIPHER_PARAMS\0" + "INCORRECT_PASSWORD\0" + "KEYGEN_FAILURE\0" + "KEY_GEN_ERROR\0" + "METHOD_NOT_SUPPORTED\0" + "MISSING_MAC\0" + "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\0" + "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\0" + "PKCS12_TOO_DEEPLY_NESTED\0" + "PRIVATE_KEY_DECODE_ERROR\0" + "PRIVATE_KEY_ENCODE_ERROR\0" + "UNKNOWN_ALGORITHM\0" + "UNKNOWN_CIPHER\0" + "UNKNOWN_CIPHER_ALGORITHM\0" + "UNKNOWN_HASH\0" + "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\0" + "BAD_E_VALUE\0" + "BAD_FIXED_HEADER_DECRYPT\0" + "BAD_PAD_BYTE_COUNT\0" + "BAD_RSA_PARAMETERS\0" + "BLOCK_TYPE_IS_NOT_01\0" + "BN_NOT_INITIALIZED\0" + "CANNOT_RECOVER_MULTI_PRIME_KEY\0" + "CRT_PARAMS_ALREADY_GIVEN\0" + "CRT_VALUES_INCORRECT\0" + "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\0" + "DATA_TOO_LARGE\0" + "DATA_TOO_LARGE_FOR_KEY_SIZE\0" + "DATA_TOO_LARGE_FOR_MODULUS\0" + "DATA_TOO_SMALL\0" + "DATA_TOO_SMALL_FOR_KEY_SIZE\0" + "DIGEST_TOO_BIG_FOR_RSA_KEY\0" + "D_E_NOT_CONGRUENT_TO_1\0" + "EMPTY_PUBLIC_KEY\0" + "FIRST_OCTET_INVALID\0" + "INCONSISTENT_SET_OF_CRT_VALUES\0" + "INTERNAL_ERROR\0" + "INVALID_MESSAGE_LENGTH\0" + "KEY_SIZE_TOO_SMALL\0" + "LAST_OCTET_INVALID\0" + "MUST_HAVE_AT_LEAST_TWO_PRIMES\0" + "NO_PUBLIC_EXPONENT\0" + "NULL_BEFORE_BLOCK_MISSING\0" + "N_NOT_EQUAL_P_Q\0" + "OAEP_DECODING_ERROR\0" + "ONLY_ONE_OF_P_Q_GIVEN\0" + "OUTPUT_BUFFER_TOO_SMALL\0" + "PADDING_CHECK_FAILED\0" + "PKCS_DECODING_ERROR\0" + "SLEN_CHECK_FAILED\0" + "SLEN_RECOVERY_FAILED\0" + "UNKNOWN_ALGORITHM_TYPE\0" + "UNKNOWN_PADDING_TYPE\0" + "VALUE_MISSING\0" + "WRONG_SIGNATURE_LENGTH\0" + "APP_DATA_IN_HANDSHAKE\0" + "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\0" + "BAD_ALERT\0" + "BAD_CHANGE_CIPHER_SPEC\0" + "BAD_DATA_RETURNED_BY_CALLBACK\0" + "BAD_DH_P_LENGTH\0" + "BAD_DIGEST_LENGTH\0" + "BAD_ECC_CERT\0" + "BAD_ECPOINT\0" + "BAD_HANDSHAKE_RECORD\0" + "BAD_HELLO_REQUEST\0" + "BAD_LENGTH\0" + "BAD_PACKET_LENGTH\0" + "BAD_RSA_ENCRYPT\0" + "BAD_SRTP_MKI_VALUE\0" + "BAD_SRTP_PROTECTION_PROFILE_LIST\0" + "BAD_SSL_FILETYPE\0" + "BAD_WRITE_RETRY\0" + "BIO_NOT_SET\0" + "CA_DN_LENGTH_MISMATCH\0" + "CA_DN_TOO_LONG\0" + "CCS_RECEIVED_EARLY\0" + "CERTIFICATE_VERIFY_FAILED\0" + "CERT_CB_ERROR\0" + "CERT_LENGTH_MISMATCH\0" + "CHANNEL_ID_NOT_P256\0" + "CHANNEL_ID_SIGNATURE_INVALID\0" + "CIPHER_OR_HASH_UNAVAILABLE\0" + "CLIENTHELLO_PARSE_FAILED\0" + "CLIENTHELLO_TLSEXT\0" + "CONNECTION_REJECTED\0" + "CONNECTION_TYPE_NOT_SET\0" + "CUSTOM_EXTENSION_ERROR\0" + "DATA_LENGTH_TOO_LONG\0" + "DECRYPTION_FAILED\0" + "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\0" + "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\0" + "DH_P_TOO_LONG\0" + "DIGEST_CHECK_FAILED\0" + "DTLS_MESSAGE_TOO_BIG\0" + "ECC_CERT_NOT_FOR_SIGNING\0" + "EMS_STATE_INCONSISTENT\0" + "ENCRYPTED_LENGTH_TOO_LONG\0" + "ERROR_ADDING_EXTENSION\0" + "ERROR_IN_RECEIVED_CIPHER_LIST\0" + "ERROR_PARSING_EXTENSION\0" + "EXCESSIVE_MESSAGE_SIZE\0" + "EXTRA_DATA_IN_MESSAGE\0" + "FRAGMENT_MISMATCH\0" + "GOT_NEXT_PROTO_WITHOUT_EXTENSION\0" + "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\0" + "HTTPS_PROXY_REQUEST\0" + "HTTP_REQUEST\0" + "INAPPROPRIATE_FALLBACK\0" + "INVALID_COMMAND\0" + "INVALID_MESSAGE\0" + "INVALID_SSL_SESSION\0" + "INVALID_TICKET_KEYS_LENGTH\0" + "LENGTH_MISMATCH\0" + "LIBRARY_HAS_NO_CIPHERS\0" + "MISSING_EXTENSION\0" + "MISSING_RSA_CERTIFICATE\0" + "MISSING_TMP_DH_KEY\0" + "MISSING_TMP_ECDH_KEY\0" + "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\0" + "MTU_TOO_SMALL\0" + "NEGOTIATED_BOTH_NPN_AND_ALPN\0" + "NESTED_GROUP\0" + "NO_CERTIFICATES_RETURNED\0" + "NO_CERTIFICATE_ASSIGNED\0" + "NO_CERTIFICATE_SET\0" + "NO_CIPHERS_AVAILABLE\0" + "NO_CIPHERS_PASSED\0" + "NO_CIPHER_MATCH\0" + "NO_COMPRESSION_SPECIFIED\0" + "NO_METHOD_SPECIFIED\0" + "NO_P256_SUPPORT\0" + "NO_PRIVATE_KEY_ASSIGNED\0" + "NO_RENEGOTIATION\0" + "NO_REQUIRED_DIGEST\0" + "NO_SHARED_CIPHER\0" + "NULL_SSL_CTX\0" + "NULL_SSL_METHOD_PASSED\0" + "OLD_SESSION_CIPHER_NOT_RETURNED\0" + "OLD_SESSION_VERSION_NOT_RETURNED\0" + "PARSE_TLSEXT\0" + "PATH_TOO_LONG\0" + "PEER_DID_NOT_RETURN_A_CERTIFICATE\0" + "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0" + "PROTOCOL_IS_SHUTDOWN\0" + "PSK_IDENTITY_NOT_FOUND\0" + "PSK_NO_CLIENT_CB\0" + "PSK_NO_SERVER_CB\0" + "READ_TIMEOUT_EXPIRED\0" + "RECORD_LENGTH_MISMATCH\0" + "RECORD_TOO_LARGE\0" + "RENEGOTIATION_ENCODING_ERR\0" + "RENEGOTIATION_MISMATCH\0" + "REQUIRED_CIPHER_MISSING\0" + "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\0" + "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\0" + "SCSV_RECEIVED_WHEN_RENEGOTIATING\0" + "SERVERHELLO_TLSEXT\0" + "SESSION_ID_CONTEXT_UNINITIALIZED\0" + "SESSION_MAY_NOT_BE_CREATED\0" + "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\0" + "SRTP_COULD_NOT_ALLOCATE_PROFILES\0" + "SRTP_UNKNOWN_PROTECTION_PROFILE\0" + "SSL3_EXT_INVALID_SERVERNAME\0" + "SSLV3_ALERT_BAD_CERTIFICATE\0" + "SSLV3_ALERT_BAD_RECORD_MAC\0" + "SSLV3_ALERT_CERTIFICATE_EXPIRED\0" + "SSLV3_ALERT_CERTIFICATE_REVOKED\0" + "SSLV3_ALERT_CERTIFICATE_UNKNOWN\0" + "SSLV3_ALERT_CLOSE_NOTIFY\0" + "SSLV3_ALERT_DECOMPRESSION_FAILURE\0" + "SSLV3_ALERT_HANDSHAKE_FAILURE\0" + "SSLV3_ALERT_ILLEGAL_PARAMETER\0" + "SSLV3_ALERT_NO_CERTIFICATE\0" + "SSLV3_ALERT_UNEXPECTED_MESSAGE\0" + "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\0" + "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\0" + "SSL_HANDSHAKE_FAILURE\0" + "SSL_SESSION_ID_CONTEXT_TOO_LONG\0" + "TLSV1_ALERT_ACCESS_DENIED\0" + "TLSV1_ALERT_DECODE_ERROR\0" + "TLSV1_ALERT_DECRYPTION_FAILED\0" + "TLSV1_ALERT_DECRYPT_ERROR\0" + "TLSV1_ALERT_EXPORT_RESTRICTION\0" + "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\0" + "TLSV1_ALERT_INSUFFICIENT_SECURITY\0" + "TLSV1_ALERT_INTERNAL_ERROR\0" + "TLSV1_ALERT_NO_RENEGOTIATION\0" + "TLSV1_ALERT_PROTOCOL_VERSION\0" + "TLSV1_ALERT_RECORD_OVERFLOW\0" + "TLSV1_ALERT_UNKNOWN_CA\0" + "TLSV1_ALERT_USER_CANCELLED\0" + "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0" + "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0" + "TLSV1_CERTIFICATE_UNOBTAINABLE\0" + "TLSV1_UNRECOGNIZED_NAME\0" + "TLSV1_UNSUPPORTED_EXTENSION\0" + "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0" + "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\0" + "TOO_MANY_EMPTY_FRAGMENTS\0" + "TOO_MANY_WARNING_ALERTS\0" + "UNABLE_TO_FIND_ECDH_PARAMETERS\0" + "UNEXPECTED_EXTENSION\0" + "UNEXPECTED_MESSAGE\0" + "UNEXPECTED_OPERATOR_IN_GROUP\0" + "UNEXPECTED_RECORD\0" + "UNKNOWN_ALERT_TYPE\0" + "UNKNOWN_CERTIFICATE_TYPE\0" + "UNKNOWN_CIPHER_RETURNED\0" + "UNKNOWN_CIPHER_TYPE\0" + "UNKNOWN_KEY_EXCHANGE_TYPE\0" + "UNKNOWN_PROTOCOL\0" + "UNKNOWN_SSL_VERSION\0" + "UNKNOWN_STATE\0" + "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\0" + "UNSUPPORTED_COMPRESSION_ALGORITHM\0" + "UNSUPPORTED_ELLIPTIC_CURVE\0" + "UNSUPPORTED_PROTOCOL\0" + "WRONG_CERTIFICATE_TYPE\0" + "WRONG_CIPHER_RETURNED\0" + "WRONG_CURVE\0" + "WRONG_MESSAGE_TYPE\0" + "WRONG_SIGNATURE_TYPE\0" + "WRONG_SSL_VERSION\0" + "WRONG_VERSION_NUMBER\0" + "X509_LIB\0" + "X509_VERIFICATION_SETUP_PROBLEMS\0" + "AKID_MISMATCH\0" + "BAD_PKCS7_VERSION\0" + "BAD_X509_FILETYPE\0" + "BASE64_DECODE_ERROR\0" + "CANT_CHECK_DH_KEY\0" + "CERT_ALREADY_IN_HASH_TABLE\0" + "CRL_ALREADY_DELTA\0" + "CRL_VERIFY_FAILURE\0" + "IDP_MISMATCH\0" + "INVALID_DIRECTORY\0" + "INVALID_FIELD_NAME\0" + "INVALID_TRUST\0" + "ISSUER_MISMATCH\0" + "KEY_TYPE_MISMATCH\0" + "KEY_VALUES_MISMATCH\0" + "LOADING_CERT_DIR\0" + "LOADING_DEFAULTS\0" + "NEWER_CRL_NOT_NEWER\0" + "NOT_PKCS7_SIGNED_DATA\0" + "NO_CERTIFICATES_INCLUDED\0" + "NO_CERT_SET_FOR_US_TO_VERIFY\0" + "NO_CRLS_INCLUDED\0" + "NO_CRL_NUMBER\0" + "PUBLIC_KEY_DECODE_ERROR\0" + "PUBLIC_KEY_ENCODE_ERROR\0" + "SHOULD_RETRY\0" + "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN\0" + "UNABLE_TO_GET_CERTS_PUBLIC_KEY\0" + "UNKNOWN_KEY_TYPE\0" + "UNKNOWN_PURPOSE_ID\0" + "UNKNOWN_TRUST_ID\0" + "WRONG_LOOKUP_TYPE\0" + "BAD_IP_ADDRESS\0" + "BAD_OBJECT\0" + "BN_DEC2BN_ERROR\0" + "BN_TO_ASN1_INTEGER_ERROR\0" + "CANNOT_FIND_FREE_FUNCTION\0" + "DIRNAME_ERROR\0" + "DISTPOINT_ALREADY_SET\0" + "DUPLICATE_ZONE_ID\0" + "ERROR_CONVERTING_ZONE\0" + "ERROR_CREATING_EXTENSION\0" + "ERROR_IN_EXTENSION\0" + "EXPECTED_A_SECTION_NAME\0" + "EXTENSION_EXISTS\0" + "EXTENSION_NAME_ERROR\0" + "EXTENSION_NOT_FOUND\0" + "EXTENSION_SETTING_NOT_SUPPORTED\0" + "EXTENSION_VALUE_ERROR\0" + "ILLEGAL_EMPTY_EXTENSION\0" + "ILLEGAL_HEX_DIGIT\0" + "INCORRECT_POLICY_SYNTAX_TAG\0" + "INVALID_BOOLEAN_STRING\0" + "INVALID_EXTENSION_STRING\0" + "INVALID_MULTIPLE_RDNS\0" + "INVALID_NAME\0" + "INVALID_NULL_ARGUMENT\0" + "INVALID_NULL_NAME\0" + "INVALID_NULL_VALUE\0" + "INVALID_NUMBERS\0" + "INVALID_OBJECT_IDENTIFIER\0" + "INVALID_OPTION\0" + "INVALID_POLICY_IDENTIFIER\0" + "INVALID_PROXY_POLICY_SETTING\0" + "INVALID_PURPOSE\0" + "INVALID_SECTION\0" + "INVALID_SYNTAX\0" + "ISSUER_DECODE_ERROR\0" + "NEED_ORGANIZATION_AND_NUMBERS\0" + "NO_CONFIG_DATABASE\0" + "NO_ISSUER_CERTIFICATE\0" + "NO_ISSUER_DETAILS\0" + "NO_POLICY_IDENTIFIER\0" + "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\0" + "NO_PUBLIC_KEY\0" + "NO_SUBJECT_DETAILS\0" + "ODD_NUMBER_OF_DIGITS\0" + "OPERATION_NOT_DEFINED\0" + "OTHERNAME_ERROR\0" + "POLICY_LANGUAGE_ALREADY_DEFINED\0" + "POLICY_PATH_LENGTH\0" + "POLICY_PATH_LENGTH_ALREADY_DEFINED\0" + "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\0" + "SECTION_NOT_FOUND\0" + "UNABLE_TO_GET_ISSUER_DETAILS\0" + "UNABLE_TO_GET_ISSUER_KEYID\0" + "UNKNOWN_BIT_STRING_ARGUMENT\0" + "UNKNOWN_EXTENSION\0" + "UNKNOWN_EXTENSION_NAME\0" + "UNKNOWN_OPTION\0" + "UNSUPPORTED_OPTION\0" + "USER_TOO_LONG\0" + ""; + diff --git a/external/boringssl/crypto/err/err_data_generate.go b/external/boringssl/crypto/err/err_data_generate.go new file mode 100644 index 0000000000..893ebffe5a --- /dev/null +++ b/external/boringssl/crypto/err/err_data_generate.go @@ -0,0 +1,284 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package main + +import ( + "bufio" + "bytes" + "errors" + "flag" + "fmt" + "io" + "os" + "sort" + "strconv" + "strings" +) + +var verbose = flag.Bool("verbose", false, "If true, prints a status message at the end.") + +// libraryNames must be kept in sync with the enum in err.h. The generated code +// will contain static assertions to enforce this. +var libraryNames = []string{ + "NONE", + "SYS", + "BN", + "RSA", + "DH", + "EVP", + "BUF", + "OBJ", + "PEM", + "DSA", + "X509", + "ASN1", + "CONF", + "CRYPTO", + "EC", + "SSL", + "BIO", + "PKCS7", + "PKCS8", + "X509V3", + "RAND", + "ENGINE", + "OCSP", + "UI", + "COMP", + "ECDSA", + "ECDH", + "HMAC", + "DIGEST", + "CIPHER", + "HKDF", + "USER", +} + +// stringList is a map from uint32 -> string which can output data for a sorted +// list as C literals. +type stringList struct { + // entries is an array of keys and offsets into |stringData|. The + // offsets are in the bottom 15 bits of each uint32 and the key is the + // top 17 bits. + entries []uint32 + // internedStrings contains the same strings as are in |stringData|, + // but allows for easy deduplication. It maps a string to its offset in + // |stringData|. + internedStrings map[string]uint32 + stringData []byte +} + +func newStringList() *stringList { + return &stringList{ + internedStrings: make(map[string]uint32), + } +} + +// offsetMask is the bottom 15 bits. It's a mask that selects the offset from a +// uint32 in entries. +const offsetMask = 0x7fff + +func (st *stringList) Add(key uint32, value string) error { + if key&offsetMask != 0 { + return errors.New("need bottom 15 bits of the key for the offset") + } + offset, ok := st.internedStrings[value] + if !ok { + offset = uint32(len(st.stringData)) + if offset&offsetMask != offset { + return errors.New("stringList overflow") + } + st.stringData = append(st.stringData, []byte(value)...) + st.stringData = append(st.stringData, 0) + st.internedStrings[value] = offset + } + + for _, existing := range st.entries { + if existing>>15 == key>>15 { + panic("duplicate entry") + } + } + st.entries = append(st.entries, key|offset) + return nil +} + +// keySlice is a type that implements sorting of entries values. +type keySlice []uint32 + +func (ks keySlice) Len() int { + return len(ks) +} + +func (ks keySlice) Less(i, j int) bool { + return (ks[i] >> 15) < (ks[j] >> 15) +} + +func (ks keySlice) Swap(i, j int) { + ks[i], ks[j] = ks[j], ks[i] +} + +func (st *stringList) buildList() []uint32 { + sort.Sort(keySlice(st.entries)) + return st.entries +} + +type stringWriter interface { + io.Writer + WriteString(string) (int, error) +} + +func (st *stringList) WriteTo(out stringWriter, name string) { + list := st.buildList() + if *verbose { + fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData)) + } + + values := "kOpenSSL" + name + "Values" + out.WriteString("const uint32_t " + values + "[] = {\n") + for _, v := range list { + fmt.Fprintf(out, " 0x%x,\n", v) + } + out.WriteString("};\n\n") + out.WriteString("const size_t " + values + "Len = sizeof(" + values + ") / sizeof(" + values + "[0]);\n\n") + + stringData := "kOpenSSL" + name + "StringData" + out.WriteString("const char " + stringData + "[] =\n \"") + for i, c := range st.stringData { + if c == 0 { + out.WriteString("\\0\"\n \"") + continue + } + out.Write(st.stringData[i : i+1]) + } + out.WriteString("\";\n\n") +} + +type errorData struct { + reasons *stringList + libraryMap map[string]uint32 +} + +func (e *errorData) readErrorDataFile(filename string) error { + inFile, err := os.Open(filename) + if err != nil { + return err + } + defer inFile.Close() + + scanner := bufio.NewScanner(inFile) + comma := []byte(",") + + lineNo := 0 + for scanner.Scan() { + lineNo++ + + line := scanner.Bytes() + if len(line) == 0 { + continue + } + parts := bytes.Split(line, comma) + if len(parts) != 3 { + return fmt.Errorf("bad line %d in %s: found %d values but want 3", lineNo, filename, len(parts)) + } + libNum, ok := e.libraryMap[string(parts[0])] + if !ok { + return fmt.Errorf("bad line %d in %s: unknown library", lineNo, filename) + } + if libNum >= 64 { + return fmt.Errorf("bad line %d in %s: library value too large", lineNo, filename) + } + key, err := strconv.ParseUint(string(parts[1]), 10 /* base */, 32 /* bit size */) + if err != nil { + return fmt.Errorf("bad line %d in %s: %s", lineNo, filename, err) + } + if key >= 2048 { + return fmt.Errorf("bad line %d in %s: key too large", lineNo, filename) + } + value := string(parts[2]) + + listKey := libNum<<26 | uint32(key)<<15 + + err = e.reasons.Add(listKey, value) + if err != nil { + return err + } + } + + return scanner.Err() +} + +func main() { + flag.Parse() + + e := &errorData{ + reasons: newStringList(), + libraryMap: make(map[string]uint32), + } + for i, name := range libraryNames { + e.libraryMap[name] = uint32(i) + 1 + } + + cwd, err := os.Open(".") + if err != nil { + panic(err) + } + names, err := cwd.Readdirnames(-1) + if err != nil { + panic(err) + } + + sort.Strings(names) + for _, name := range names { + if !strings.HasSuffix(name, ".errordata") { + continue + } + if err := e.readErrorDataFile(name); err != nil { + panic(err) + } + } + + out := os.Stdout + + out.WriteString(`/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + /* This file was generated by err_data_generate.go. */ + +#include +#include +#include + + +`) + + for i, name := range libraryNames { + fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_LIB_%s == %d, library_values_changed_%d);\n", name, i+1, i+1) + } + fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == %d, library_values_changed_num);\n", len(libraryNames)+1) + out.WriteString("\n") + + e.reasons.WriteTo(out, "Reason") +} diff --git a/external/boringssl/crypto/err/err_test.cc b/external/boringssl/crypto/err/err_test.cc new file mode 100644 index 0000000000..d69135585d --- /dev/null +++ b/external/boringssl/crypto/err/err_test.cc @@ -0,0 +1,162 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include + + +static bool TestOverflow() { + for (unsigned i = 0; i < ERR_NUM_ERRORS*2; i++) { + ERR_put_error(1, 0 /* unused */, i+1, "test", 1); + } + + for (unsigned 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 || ((unsigned)ERR_GET_REASON(err)) != i + ERR_NUM_ERRORS + 2) { + fprintf(stderr, "ERR_get_error failed at %u\n", i); + return false; + } + } + + if (ERR_get_error() != 0) { + fprintf(stderr, "ERR_get_error more than the expected number of values.\n"); + return false; + } + + return true; +} + +static bool TestPutError() { + if (ERR_get_error() != 0) { + fprintf(stderr, "ERR_get_error returned value before an error was added.\n"); + return false; + } + + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_add_error_data(1, "testing"); + + int peeked_line, line, peeked_flags, flags; + const char *peeked_file, *file, *peeked_data, *data; + uint32_t peeked_packed_error = + ERR_peek_error_line_data(&peeked_file, &peeked_line, &peeked_data, + &peeked_flags); + uint32_t 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 false; + } + + if (strcmp(file, "test") != 0 || + line != 4 || + (flags & ERR_FLAG_STRING) == 0 || + ERR_GET_LIB(packed_error) != 1 || + ERR_GET_REASON(packed_error) != 2 || + strcmp(data, "testing") != 0) { + fprintf(stderr, "Bad error data returned.\n"); + return false; + } + + return true; +} + +static bool TestClearError() { + if (ERR_get_error() != 0) { + fprintf(stderr, "ERR_get_error returned value before an error was added.\n"); + return false; + } + + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_clear_error(); + + if (ERR_get_error() != 0) { + fprintf(stderr, "Error remained after clearing.\n"); + return false; + } + + return true; +} + +static bool TestPrint() { + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_add_error_data(1, "testing"); + uint32_t packed_error = ERR_get_error(); + + char buf[256]; + for (size_t i = 0; i <= sizeof(buf); i++) { + ERR_error_string_n(packed_error, buf, i); + } + + return true; +} + +static bool TestRelease() { + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_remove_thread_state(NULL); + return true; +} + +static bool HasSuffix(const char *str, const char *suffix) { + size_t suffix_len = strlen(suffix); + size_t str_len = strlen(str); + if (str_len < suffix_len) { + return false; + } + return strcmp(str + str_len - suffix_len, suffix) == 0; +} + +static bool TestPutMacro() { + int expected_line = __LINE__ + 1; + OPENSSL_PUT_ERROR(USER, ERR_R_INTERNAL_ERROR); + + int line; + const char *file; + uint32_t error = ERR_get_error_line(&file, &line); + + if (!HasSuffix(file, "err_test.cc") || + line != expected_line || + ERR_GET_LIB(error) != ERR_LIB_USER || + ERR_GET_REASON(error) != ERR_R_INTERNAL_ERROR) { + fprintf(stderr, "Bad error data returned.\n"); + return false; + } + + return true; +} + +int main() { + CRYPTO_library_init(); + + if (!TestOverflow() || + !TestPutError() || + !TestClearError() || + !TestPrint() || + !TestRelease() || + !TestPutMacro()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/err/evp.errordata b/external/boringssl/crypto/err/evp.errordata new file mode 100644 index 0000000000..a482f7693e --- /dev/null +++ b/external/boringssl/crypto/err/evp.errordata @@ -0,0 +1,30 @@ +EVP,100,BUFFER_TOO_SMALL +EVP,101,COMMAND_NOT_SUPPORTED +EVP,102,DECODE_ERROR +EVP,103,DIFFERENT_KEY_TYPES +EVP,104,DIFFERENT_PARAMETERS +EVP,105,ENCODE_ERROR +EVP,106,EXPECTING_AN_EC_KEY_KEY +EVP,107,EXPECTING_AN_RSA_KEY +EVP,108,EXPECTING_A_DSA_KEY +EVP,109,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE +EVP,110,INVALID_DIGEST_LENGTH +EVP,111,INVALID_DIGEST_TYPE +EVP,112,INVALID_KEYBITS +EVP,113,INVALID_MGF1_MD +EVP,114,INVALID_OPERATION +EVP,115,INVALID_PADDING_MODE +EVP,116,INVALID_PSS_SALTLEN +EVP,117,KEYS_NOT_SET +EVP,118,MISSING_PARAMETERS +EVP,119,NO_DEFAULT_DIGEST +EVP,120,NO_KEY_SET +EVP,121,NO_MDC2_SUPPORT +EVP,122,NO_NID_FOR_CURVE +EVP,123,NO_OPERATION_SET +EVP,124,NO_PARAMETERS_SET +EVP,125,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE +EVP,126,OPERATON_NOT_INITIALIZED +EVP,127,UNKNOWN_PUBLIC_KEY_TYPE +EVP,128,UNSUPPORTED_ALGORITHM +EVP,129,UNSUPPORTED_PUBLIC_KEY_TYPE diff --git a/external/boringssl/crypto/err/hkdf.errordata b/external/boringssl/crypto/err/hkdf.errordata new file mode 100644 index 0000000000..84866dee16 --- /dev/null +++ b/external/boringssl/crypto/err/hkdf.errordata @@ -0,0 +1 @@ +HKDF,100,OUTPUT_TOO_LARGE diff --git a/external/boringssl/crypto/err/obj.errordata b/external/boringssl/crypto/err/obj.errordata new file mode 100644 index 0000000000..c54435ea97 --- /dev/null +++ b/external/boringssl/crypto/err/obj.errordata @@ -0,0 +1 @@ +OBJ,100,UNKNOWN_NID diff --git a/external/boringssl/crypto/err/pem.errordata b/external/boringssl/crypto/err/pem.errordata new file mode 100644 index 0000000000..2a4b73af2d --- /dev/null +++ b/external/boringssl/crypto/err/pem.errordata @@ -0,0 +1,15 @@ +PEM,100,BAD_BASE64_DECODE +PEM,101,BAD_DECRYPT +PEM,102,BAD_END_LINE +PEM,103,BAD_IV_CHARS +PEM,104,BAD_PASSWORD_READ +PEM,105,CIPHER_IS_NULL +PEM,106,ERROR_CONVERTING_PRIVATE_KEY +PEM,107,NOT_DEK_INFO +PEM,108,NOT_ENCRYPTED +PEM,109,NOT_PROC_TYPE +PEM,110,NO_START_LINE +PEM,111,READ_KEY +PEM,112,SHORT_HEADER +PEM,113,UNSUPPORTED_CIPHER +PEM,114,UNSUPPORTED_ENCRYPTION diff --git a/external/boringssl/crypto/err/pkcs8.errordata b/external/boringssl/crypto/err/pkcs8.errordata new file mode 100644 index 0000000000..0eb5083bc2 --- /dev/null +++ b/external/boringssl/crypto/err/pkcs8.errordata @@ -0,0 +1,25 @@ +PKCS8,100,BAD_PKCS12_DATA +PKCS8,101,BAD_PKCS12_VERSION +PKCS8,102,CIPHER_HAS_NO_OBJECT_IDENTIFIER +PKCS8,103,CRYPT_ERROR +PKCS8,104,DECODE_ERROR +PKCS8,105,ENCODE_ERROR +PKCS8,106,ENCRYPT_ERROR +PKCS8,107,ERROR_SETTING_CIPHER_PARAMS +PKCS8,108,INCORRECT_PASSWORD +PKCS8,109,KEYGEN_FAILURE +PKCS8,110,KEY_GEN_ERROR +PKCS8,111,METHOD_NOT_SUPPORTED +PKCS8,112,MISSING_MAC +PKCS8,113,MULTIPLE_PRIVATE_KEYS_IN_PKCS12 +PKCS8,114,PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED +PKCS8,115,PKCS12_TOO_DEEPLY_NESTED +PKCS8,116,PRIVATE_KEY_DECODE_ERROR +PKCS8,117,PRIVATE_KEY_ENCODE_ERROR +PKCS8,118,TOO_LONG +PKCS8,119,UNKNOWN_ALGORITHM +PKCS8,120,UNKNOWN_CIPHER +PKCS8,121,UNKNOWN_CIPHER_ALGORITHM +PKCS8,122,UNKNOWN_DIGEST +PKCS8,123,UNKNOWN_HASH +PKCS8,124,UNSUPPORTED_PRIVATE_KEY_ALGORITHM diff --git a/external/boringssl/crypto/err/rsa.errordata b/external/boringssl/crypto/err/rsa.errordata new file mode 100644 index 0000000000..62d286cc38 --- /dev/null +++ b/external/boringssl/crypto/err/rsa.errordata @@ -0,0 +1,46 @@ +RSA,100,BAD_ENCODING +RSA,101,BAD_E_VALUE +RSA,102,BAD_FIXED_HEADER_DECRYPT +RSA,103,BAD_PAD_BYTE_COUNT +RSA,104,BAD_RSA_PARAMETERS +RSA,105,BAD_SIGNATURE +RSA,106,BAD_VERSION +RSA,107,BLOCK_TYPE_IS_NOT_01 +RSA,108,BN_NOT_INITIALIZED +RSA,109,CANNOT_RECOVER_MULTI_PRIME_KEY +RSA,110,CRT_PARAMS_ALREADY_GIVEN +RSA,111,CRT_VALUES_INCORRECT +RSA,112,DATA_LEN_NOT_EQUAL_TO_MOD_LEN +RSA,113,DATA_TOO_LARGE +RSA,114,DATA_TOO_LARGE_FOR_KEY_SIZE +RSA,115,DATA_TOO_LARGE_FOR_MODULUS +RSA,116,DATA_TOO_SMALL +RSA,117,DATA_TOO_SMALL_FOR_KEY_SIZE +RSA,118,DIGEST_TOO_BIG_FOR_RSA_KEY +RSA,119,D_E_NOT_CONGRUENT_TO_1 +RSA,120,EMPTY_PUBLIC_KEY +RSA,121,ENCODE_ERROR +RSA,122,FIRST_OCTET_INVALID +RSA,123,INCONSISTENT_SET_OF_CRT_VALUES +RSA,124,INTERNAL_ERROR +RSA,125,INVALID_MESSAGE_LENGTH +RSA,126,KEY_SIZE_TOO_SMALL +RSA,127,LAST_OCTET_INVALID +RSA,128,MODULUS_TOO_LARGE +RSA,129,MUST_HAVE_AT_LEAST_TWO_PRIMES +RSA,130,NO_PUBLIC_EXPONENT +RSA,131,NULL_BEFORE_BLOCK_MISSING +RSA,132,N_NOT_EQUAL_P_Q +RSA,133,OAEP_DECODING_ERROR +RSA,134,ONLY_ONE_OF_P_Q_GIVEN +RSA,135,OUTPUT_BUFFER_TOO_SMALL +RSA,136,PADDING_CHECK_FAILED +RSA,137,PKCS_DECODING_ERROR +RSA,138,SLEN_CHECK_FAILED +RSA,139,SLEN_RECOVERY_FAILED +RSA,140,TOO_LONG +RSA,141,TOO_MANY_ITERATIONS +RSA,142,UNKNOWN_ALGORITHM_TYPE +RSA,143,UNKNOWN_PADDING_TYPE +RSA,144,VALUE_MISSING +RSA,145,WRONG_SIGNATURE_LENGTH diff --git a/external/boringssl/crypto/err/ssl.errordata b/external/boringssl/crypto/err/ssl.errordata new file mode 100644 index 0000000000..dfe4ac8127 --- /dev/null +++ b/external/boringssl/crypto/err/ssl.errordata @@ -0,0 +1,181 @@ +SSL,100,APP_DATA_IN_HANDSHAKE +SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT +SSL,102,BAD_ALERT +SSL,103,BAD_CHANGE_CIPHER_SPEC +SSL,104,BAD_DATA_RETURNED_BY_CALLBACK +SSL,105,BAD_DH_P_LENGTH +SSL,106,BAD_DIGEST_LENGTH +SSL,107,BAD_ECC_CERT +SSL,108,BAD_ECPOINT +SSL,109,BAD_HANDSHAKE_RECORD +SSL,110,BAD_HELLO_REQUEST +SSL,111,BAD_LENGTH +SSL,112,BAD_PACKET_LENGTH +SSL,113,BAD_RSA_ENCRYPT +SSL,114,BAD_SIGNATURE +SSL,115,BAD_SRTP_MKI_VALUE +SSL,116,BAD_SRTP_PROTECTION_PROFILE_LIST +SSL,117,BAD_SSL_FILETYPE +SSL,118,BAD_WRITE_RETRY +SSL,119,BIO_NOT_SET +SSL,120,BN_LIB +SSL,121,BUFFER_TOO_SMALL +SSL,122,CA_DN_LENGTH_MISMATCH +SSL,123,CA_DN_TOO_LONG +SSL,124,CCS_RECEIVED_EARLY +SSL,125,CERTIFICATE_VERIFY_FAILED +SSL,126,CERT_CB_ERROR +SSL,127,CERT_LENGTH_MISMATCH +SSL,128,CHANNEL_ID_NOT_P256 +SSL,129,CHANNEL_ID_SIGNATURE_INVALID +SSL,130,CIPHER_OR_HASH_UNAVAILABLE +SSL,131,CLIENTHELLO_PARSE_FAILED +SSL,132,CLIENTHELLO_TLSEXT +SSL,133,CONNECTION_REJECTED +SSL,134,CONNECTION_TYPE_NOT_SET +SSL,135,CUSTOM_EXTENSION_ERROR +SSL,136,DATA_LENGTH_TOO_LONG +SSL,137,DECODE_ERROR +SSL,138,DECRYPTION_FAILED +SSL,139,DECRYPTION_FAILED_OR_BAD_RECORD_MAC +SSL,140,DH_PUBLIC_VALUE_LENGTH_IS_WRONG +SSL,141,DH_P_TOO_LONG +SSL,142,DIGEST_CHECK_FAILED +SSL,143,DTLS_MESSAGE_TOO_BIG +SSL,144,ECC_CERT_NOT_FOR_SIGNING +SSL,145,EMS_STATE_INCONSISTENT +SSL,146,ENCRYPTED_LENGTH_TOO_LONG +SSL,147,ERROR_ADDING_EXTENSION +SSL,148,ERROR_IN_RECEIVED_CIPHER_LIST +SSL,149,ERROR_PARSING_EXTENSION +SSL,150,EXCESSIVE_MESSAGE_SIZE +SSL,151,EXTRA_DATA_IN_MESSAGE +SSL,152,FRAGMENT_MISMATCH +SSL,153,GOT_NEXT_PROTO_WITHOUT_EXTENSION +SSL,154,HANDSHAKE_FAILURE_ON_CLIENT_HELLO +SSL,155,HTTPS_PROXY_REQUEST +SSL,156,HTTP_REQUEST +SSL,157,INAPPROPRIATE_FALLBACK +SSL,158,INVALID_COMMAND +SSL,159,INVALID_MESSAGE +SSL,160,INVALID_SSL_SESSION +SSL,161,INVALID_TICKET_KEYS_LENGTH +SSL,162,LENGTH_MISMATCH +SSL,163,LIBRARY_HAS_NO_CIPHERS +SSL,164,MISSING_EXTENSION +SSL,165,MISSING_RSA_CERTIFICATE +SSL,166,MISSING_TMP_DH_KEY +SSL,167,MISSING_TMP_ECDH_KEY +SSL,168,MIXED_SPECIAL_OPERATOR_WITH_GROUPS +SSL,169,MTU_TOO_SMALL +SSL,170,NEGOTIATED_BOTH_NPN_AND_ALPN +SSL,171,NESTED_GROUP +SSL,172,NO_CERTIFICATES_RETURNED +SSL,173,NO_CERTIFICATE_ASSIGNED +SSL,174,NO_CERTIFICATE_SET +SSL,175,NO_CIPHERS_AVAILABLE +SSL,176,NO_CIPHERS_PASSED +SSL,177,NO_CIPHER_MATCH +SSL,178,NO_COMPRESSION_SPECIFIED +SSL,179,NO_METHOD_SPECIFIED +SSL,180,NO_P256_SUPPORT +SSL,181,NO_PRIVATE_KEY_ASSIGNED +SSL,182,NO_RENEGOTIATION +SSL,183,NO_REQUIRED_DIGEST +SSL,184,NO_SHARED_CIPHER +SSL,185,NULL_SSL_CTX +SSL,186,NULL_SSL_METHOD_PASSED +SSL,187,OLD_SESSION_CIPHER_NOT_RETURNED +SSL,188,OLD_SESSION_VERSION_NOT_RETURNED +SSL,189,OUTPUT_ALIASES_INPUT +SSL,190,PARSE_TLSEXT +SSL,191,PATH_TOO_LONG +SSL,192,PEER_DID_NOT_RETURN_A_CERTIFICATE +SSL,193,PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE +SSL,194,PROTOCOL_IS_SHUTDOWN +SSL,195,PSK_IDENTITY_NOT_FOUND +SSL,196,PSK_NO_CLIENT_CB +SSL,197,PSK_NO_SERVER_CB +SSL,198,READ_TIMEOUT_EXPIRED +SSL,199,RECORD_LENGTH_MISMATCH +SSL,200,RECORD_TOO_LARGE +SSL,201,RENEGOTIATION_ENCODING_ERR +SSL,202,RENEGOTIATION_MISMATCH +SSL,203,REQUIRED_CIPHER_MISSING +SSL,204,RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION +SSL,205,RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION +SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING +SSL,207,SERVERHELLO_TLSEXT +SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED +SSL,209,SESSION_MAY_NOT_BE_CREATED +SSL,250,SHUTDOWN_WHILE_IN_INIT +SSL,210,SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER +SSL,211,SRTP_COULD_NOT_ALLOCATE_PROFILES +SSL,212,SRTP_UNKNOWN_PROTECTION_PROFILE +SSL,213,SSL3_EXT_INVALID_SERVERNAME +SSL,1042,SSLV3_ALERT_BAD_CERTIFICATE +SSL,1020,SSLV3_ALERT_BAD_RECORD_MAC +SSL,1045,SSLV3_ALERT_CERTIFICATE_EXPIRED +SSL,1044,SSLV3_ALERT_CERTIFICATE_REVOKED +SSL,1046,SSLV3_ALERT_CERTIFICATE_UNKNOWN +SSL,1000,SSLV3_ALERT_CLOSE_NOTIFY +SSL,1030,SSLV3_ALERT_DECOMPRESSION_FAILURE +SSL,1040,SSLV3_ALERT_HANDSHAKE_FAILURE +SSL,1047,SSLV3_ALERT_ILLEGAL_PARAMETER +SSL,1041,SSLV3_ALERT_NO_CERTIFICATE +SSL,1010,SSLV3_ALERT_UNEXPECTED_MESSAGE +SSL,1043,SSLV3_ALERT_UNSUPPORTED_CERTIFICATE +SSL,214,SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION +SSL,215,SSL_HANDSHAKE_FAILURE +SSL,216,SSL_SESSION_ID_CONTEXT_TOO_LONG +SSL,1049,TLSV1_ALERT_ACCESS_DENIED +SSL,1050,TLSV1_ALERT_DECODE_ERROR +SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED +SSL,1051,TLSV1_ALERT_DECRYPT_ERROR +SSL,1060,TLSV1_ALERT_EXPORT_RESTRICTION +SSL,1086,TLSV1_ALERT_INAPPROPRIATE_FALLBACK +SSL,1071,TLSV1_ALERT_INSUFFICIENT_SECURITY +SSL,1080,TLSV1_ALERT_INTERNAL_ERROR +SSL,1100,TLSV1_ALERT_NO_RENEGOTIATION +SSL,1070,TLSV1_ALERT_PROTOCOL_VERSION +SSL,1022,TLSV1_ALERT_RECORD_OVERFLOW +SSL,1048,TLSV1_ALERT_UNKNOWN_CA +SSL,1090,TLSV1_ALERT_USER_CANCELLED +SSL,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE +SSL,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE +SSL,1111,TLSV1_CERTIFICATE_UNOBTAINABLE +SSL,1112,TLSV1_UNRECOGNIZED_NAME +SSL,1110,TLSV1_UNSUPPORTED_EXTENSION +SSL,217,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST +SSL,218,TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG +SSL,219,TOO_MANY_EMPTY_FRAGMENTS +SSL,220,TOO_MANY_WARNING_ALERTS +SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS +SSL,222,UNEXPECTED_EXTENSION +SSL,223,UNEXPECTED_MESSAGE +SSL,224,UNEXPECTED_OPERATOR_IN_GROUP +SSL,225,UNEXPECTED_RECORD +SSL,226,UNINITIALIZED +SSL,227,UNKNOWN_ALERT_TYPE +SSL,228,UNKNOWN_CERTIFICATE_TYPE +SSL,229,UNKNOWN_CIPHER_RETURNED +SSL,230,UNKNOWN_CIPHER_TYPE +SSL,231,UNKNOWN_DIGEST +SSL,232,UNKNOWN_KEY_EXCHANGE_TYPE +SSL,233,UNKNOWN_PROTOCOL +SSL,234,UNKNOWN_SSL_VERSION +SSL,235,UNKNOWN_STATE +SSL,236,UNSAFE_LEGACY_RENEGOTIATION_DISABLED +SSL,237,UNSUPPORTED_CIPHER +SSL,238,UNSUPPORTED_COMPRESSION_ALGORITHM +SSL,239,UNSUPPORTED_ELLIPTIC_CURVE +SSL,240,UNSUPPORTED_PROTOCOL +SSL,241,WRONG_CERTIFICATE_TYPE +SSL,242,WRONG_CIPHER_RETURNED +SSL,243,WRONG_CURVE +SSL,244,WRONG_MESSAGE_TYPE +SSL,245,WRONG_SIGNATURE_TYPE +SSL,246,WRONG_SSL_VERSION +SSL,247,WRONG_VERSION_NUMBER +SSL,248,X509_LIB +SSL,249,X509_VERIFICATION_SETUP_PROBLEMS diff --git a/external/boringssl/crypto/err/x509.errordata b/external/boringssl/crypto/err/x509.errordata new file mode 100644 index 0000000000..5687c30c9b --- /dev/null +++ b/external/boringssl/crypto/err/x509.errordata @@ -0,0 +1,36 @@ +X509,100,AKID_MISMATCH +X509,101,BAD_PKCS7_VERSION +X509,102,BAD_X509_FILETYPE +X509,103,BASE64_DECODE_ERROR +X509,104,CANT_CHECK_DH_KEY +X509,105,CERT_ALREADY_IN_HASH_TABLE +X509,106,CRL_ALREADY_DELTA +X509,107,CRL_VERIFY_FAILURE +X509,108,IDP_MISMATCH +X509,109,INVALID_BIT_STRING_BITS_LEFT +X509,110,INVALID_DIRECTORY +X509,111,INVALID_FIELD_NAME +X509,112,INVALID_PSS_PARAMETERS +X509,113,INVALID_TRUST +X509,114,ISSUER_MISMATCH +X509,115,KEY_TYPE_MISMATCH +X509,116,KEY_VALUES_MISMATCH +X509,117,LOADING_CERT_DIR +X509,118,LOADING_DEFAULTS +X509,135,NAME_TOO_LONG +X509,119,NEWER_CRL_NOT_NEWER +X509,120,NOT_PKCS7_SIGNED_DATA +X509,121,NO_CERTIFICATES_INCLUDED +X509,122,NO_CERT_SET_FOR_US_TO_VERIFY +X509,123,NO_CRLS_INCLUDED +X509,124,NO_CRL_NUMBER +X509,125,PUBLIC_KEY_DECODE_ERROR +X509,126,PUBLIC_KEY_ENCODE_ERROR +X509,127,SHOULD_RETRY +X509,128,UNKNOWN_KEY_TYPE +X509,129,UNKNOWN_NID +X509,130,UNKNOWN_PURPOSE_ID +X509,131,UNKNOWN_TRUST_ID +X509,132,UNSUPPORTED_ALGORITHM +X509,133,WRONG_LOOKUP_TYPE +X509,134,WRONG_TYPE diff --git a/external/boringssl/crypto/err/x509v3.errordata b/external/boringssl/crypto/err/x509v3.errordata new file mode 100644 index 0000000000..e53b7800a2 --- /dev/null +++ b/external/boringssl/crypto/err/x509v3.errordata @@ -0,0 +1,63 @@ +X509V3,100,BAD_IP_ADDRESS +X509V3,101,BAD_OBJECT +X509V3,102,BN_DEC2BN_ERROR +X509V3,103,BN_TO_ASN1_INTEGER_ERROR +X509V3,104,CANNOT_FIND_FREE_FUNCTION +X509V3,105,DIRNAME_ERROR +X509V3,106,DISTPOINT_ALREADY_SET +X509V3,107,DUPLICATE_ZONE_ID +X509V3,108,ERROR_CONVERTING_ZONE +X509V3,109,ERROR_CREATING_EXTENSION +X509V3,110,ERROR_IN_EXTENSION +X509V3,111,EXPECTED_A_SECTION_NAME +X509V3,112,EXTENSION_EXISTS +X509V3,113,EXTENSION_NAME_ERROR +X509V3,114,EXTENSION_NOT_FOUND +X509V3,115,EXTENSION_SETTING_NOT_SUPPORTED +X509V3,116,EXTENSION_VALUE_ERROR +X509V3,117,ILLEGAL_EMPTY_EXTENSION +X509V3,118,ILLEGAL_HEX_DIGIT +X509V3,119,INCORRECT_POLICY_SYNTAX_TAG +X509V3,120,INVALID_BOOLEAN_STRING +X509V3,121,INVALID_EXTENSION_STRING +X509V3,122,INVALID_MULTIPLE_RDNS +X509V3,123,INVALID_NAME +X509V3,124,INVALID_NULL_ARGUMENT +X509V3,125,INVALID_NULL_NAME +X509V3,126,INVALID_NULL_VALUE +X509V3,127,INVALID_NUMBER +X509V3,128,INVALID_NUMBERS +X509V3,129,INVALID_OBJECT_IDENTIFIER +X509V3,130,INVALID_OPTION +X509V3,131,INVALID_POLICY_IDENTIFIER +X509V3,132,INVALID_PROXY_POLICY_SETTING +X509V3,133,INVALID_PURPOSE +X509V3,134,INVALID_SECTION +X509V3,135,INVALID_SYNTAX +X509V3,136,ISSUER_DECODE_ERROR +X509V3,137,MISSING_VALUE +X509V3,138,NEED_ORGANIZATION_AND_NUMBERS +X509V3,139,NO_CONFIG_DATABASE +X509V3,140,NO_ISSUER_CERTIFICATE +X509V3,141,NO_ISSUER_DETAILS +X509V3,142,NO_POLICY_IDENTIFIER +X509V3,143,NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED +X509V3,144,NO_PUBLIC_KEY +X509V3,145,NO_SUBJECT_DETAILS +X509V3,146,ODD_NUMBER_OF_DIGITS +X509V3,147,OPERATION_NOT_DEFINED +X509V3,148,OTHERNAME_ERROR +X509V3,149,POLICY_LANGUAGE_ALREADY_DEFINED +X509V3,150,POLICY_PATH_LENGTH +X509V3,151,POLICY_PATH_LENGTH_ALREADY_DEFINED +X509V3,152,POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY +X509V3,153,SECTION_NOT_FOUND +X509V3,154,UNABLE_TO_GET_ISSUER_DETAILS +X509V3,155,UNABLE_TO_GET_ISSUER_KEYID +X509V3,156,UNKNOWN_BIT_STRING_ARGUMENT +X509V3,157,UNKNOWN_EXTENSION +X509V3,158,UNKNOWN_EXTENSION_NAME +X509V3,159,UNKNOWN_OPTION +X509V3,160,UNSUPPORTED_OPTION +X509V3,161,UNSUPPORTED_TYPE +X509V3,162,USER_TOO_LONG diff --git a/external/boringssl/crypto/evp/CMakeLists.txt b/external/boringssl/crypto/evp/CMakeLists.txt new file mode 100644 index 0000000000..1174be6381 --- /dev/null +++ b/external/boringssl/crypto/evp/CMakeLists.txt @@ -0,0 +1,52 @@ +include_directories(../../include) + +add_library( + evp + + OBJECT + + digestsign.c + evp.c + evp_asn1.c + evp_ctx.c + p_dsa_asn1.c + p_ec.c + p_ec_asn1.c + p_rsa.c + p_rsa_asn1.c + pbkdf.c + print.c + sign.c +) + + +if(ENABLE_TESTS) +add_executable( + evp_extra_test + + evp_extra_test.cc + + $ +) + +add_executable( + evp_test + + evp_test.cc + + $ +) + +add_executable( + pbkdf_test + + pbkdf_test.cc + + $ +) + +target_link_libraries(evp_extra_test crypto) +target_link_libraries(evp_test crypto) +target_link_libraries(pbkdf_test crypto) +add_dependencies(all_tests evp_extra_test evp_test pbkdf_test) +endif() diff --git a/external/boringssl/crypto/evp/digestsign.c b/external/boringssl/crypto/evp/digestsign.c new file mode 100644 index 0000000000..69c483ad78 --- /dev/null +++ b/external/boringssl/crypto/evp/digestsign.c @@ -0,0 +1,159 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006,2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include "internal.h" +#include "../digest/internal.h" + + +static const struct evp_md_pctx_ops md_pctx_ops = { + EVP_PKEY_CTX_free, + EVP_PKEY_CTX_dup, +}; + +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) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST); + return 0; + } + + if (is_verify) { + if (!EVP_PKEY_verify_init(ctx->pctx)) { + return 0; + } + } else { + if (!EVP_PKEY_sign_init(ctx->pctx)) { + return 0; + } + } + if (!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) { + 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) { + if (out_sig) { + EVP_MD_CTX tmp_ctx; + int ret; + uint8_t md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + + EVP_MD_CTX_init(&tmp_ctx); + ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) && + EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) && + EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen); + EVP_MD_CTX_cleanup(&tmp_ctx); + + return ret; + } 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; + int ret; + uint8_t md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + + EVP_MD_CTX_init(&tmp_ctx); + ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) && + EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) && + EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen); + EVP_MD_CTX_cleanup(&tmp_ctx); + + return ret; +} diff --git a/external/boringssl/crypto/evp/evp.c b/external/boringssl/crypto/evp/evp.c new file mode 100644 index 0000000000..ee207f9b86 --- /dev/null +++ b/external/boringssl/crypto/evp/evp.c @@ -0,0 +1,365 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +EVP_PKEY *EVP_PKEY_new(void) { + EVP_PKEY *ret; + + ret = OPENSSL_malloc(sizeof(EVP_PKEY)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EVP, 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_refcount_dec_and_test_zero(&pkey->references)) { + return; + } + + free_it(pkey); + OPENSSL_free(pkey); +} + +EVP_PKEY *EVP_PKEY_up_ref(EVP_PKEY *pkey) { + CRYPTO_refcount_inc(&pkey->references); + return 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; +} + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { + if (to->type != from->type) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); + goto err; + } + + if (EVP_PKEY_missing_parameters(from)) { + OPENSSL_PUT_ERROR(EVP, 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; +} + +/* 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. */ +static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) { + switch (nid) { + case EVP_PKEY_RSA: + return &rsa_asn1_meth; + case EVP_PKEY_EC: + return &ec_asn1_meth; + case EVP_PKEY_DSA: + return &dsa_asn1_meth; + default: + return NULL; + } +} + +int EVP_PKEY_type(int nid) { + const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(nid); + if (meth == NULL) { + return NID_undef; + } + return meth->pkey_id; +} + +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_get0_RSA(EVP_PKEY *pkey) { + if (pkey->type != EVP_PKEY_RSA) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_RSA_KEY); + return NULL; + } + return pkey->pkey.rsa; +} + +RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) { + RSA *rsa = EVP_PKEY_get0_RSA(pkey); + if (rsa != NULL) { + RSA_up_ref(rsa); + } + return 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_get0_DSA(EVP_PKEY *pkey) { + if (pkey->type != EVP_PKEY_DSA) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DSA_KEY); + return NULL; + } + return pkey->pkey.dsa; +} + +DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) { + DSA *dsa = EVP_PKEY_get0_DSA(pkey); + if (dsa != NULL) { + DSA_up_ref(dsa); + } + return 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_get0_EC_KEY(EVP_PKEY *pkey) { + if (pkey->type != EVP_PKEY_EC) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_EC_KEY_KEY); + return NULL; + } + return pkey->pkey.ec; +} + +EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) { + EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (ec_key != NULL) { + EC_KEY_up_ref(ec_key); + } + return ec_key; +} + +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; +} + +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(type); + if (ameth == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + ERR_add_error_dataf("algorithm %d", 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; +} + +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 OPENSSL_add_all_algorithms_conf(void) {} + +void OpenSSL_add_all_ciphers(void) {} + +void OpenSSL_add_all_digests(void) {} + +void EVP_cleanup(void) {} diff --git a/external/boringssl/crypto/evp/evp_asn1.c b/external/boringssl/crypto/evp/evp_asn1.c new file mode 100644 index 0000000000..3681d4fcd6 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_asn1.c @@ -0,0 +1,336 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = { + &rsa_asn1_meth, + &ec_asn1_meth, + &dsa_asn1_meth, +}; + +static int parse_key_type(CBS *cbs, int *out_type) { + CBS oid; + if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) { + return 0; + } + + unsigned i; + for (i = 0; i < sizeof(kASN1Methods)/sizeof(kASN1Methods[0]); i++) { + const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i]; + if (CBS_len(&oid) == method->oid_len && + memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) { + *out_type = method->pkey_id; + return 1; + } + } + + return 0; +} + +EVP_PKEY *EVP_parse_public_key(CBS *cbs) { + /* Parse the SubjectPublicKeyInfo. */ + CBS spki, algorithm, key; + int type; + uint8_t padding; + if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !parse_key_type(&algorithm, &type) || + !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) || + CBS_len(&spki) != 0 || + /* Every key type defined encodes the key as a byte string with the same + * conversion to BIT STRING. */ + !CBS_get_u8(&key, &padding) || + padding != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* Set up an |EVP_PKEY| of the appropriate type. */ + EVP_PKEY *ret = EVP_PKEY_new(); + if (ret == NULL || + !EVP_PKEY_set_type(ret, type)) { + goto err; + } + + /* Call into the type-specific SPKI decoding function. */ + if (ret->ameth->pub_decode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + goto err; + } + if (!ret->ameth->pub_decode(ret, &algorithm, &key)) { + goto err; + } + + return ret; + +err: + EVP_PKEY_free(ret); + return NULL; +} + +int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) { + if (key->ameth == NULL || key->ameth->pub_encode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + + return key->ameth->pub_encode(cbb, key); +} + +EVP_PKEY *EVP_parse_private_key(CBS *cbs) { + /* Parse the PrivateKeyInfo. */ + CBS pkcs8, algorithm, key; + uint64_t version; + int type; + if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&pkcs8, &version) || + version != 0 || + !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !parse_key_type(&algorithm, &type) || + !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* A PrivateKeyInfo ends with a SET of Attributes which we ignore. */ + + /* Set up an |EVP_PKEY| of the appropriate type. */ + EVP_PKEY *ret = EVP_PKEY_new(); + if (ret == NULL || + !EVP_PKEY_set_type(ret, type)) { + goto err; + } + + /* Call into the type-specific PrivateKeyInfo decoding function. */ + if (ret->ameth->priv_decode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + goto err; + } + if (!ret->ameth->priv_decode(ret, &algorithm, &key)) { + goto err; + } + + return ret; + +err: + EVP_PKEY_free(ret); + return NULL; +} + +int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) { + if (key->ameth == NULL || key->ameth->priv_encode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + + return key->ameth->priv_encode(cbb, key); +} + +static EVP_PKEY *old_priv_decode(CBS *cbs, int type) { + EVP_PKEY *ret = EVP_PKEY_new(); + if (ret == NULL) { + return NULL; + } + + switch (type) { + case EVP_PKEY_EC: { + EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL); + if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) { + EC_KEY_free(ec_key); + goto err; + } + return ret; + } + case EVP_PKEY_DSA: { + DSA *dsa = DSA_parse_private_key(cbs); + if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) { + DSA_free(dsa); + goto err; + } + return ret; + } + case EVP_PKEY_RSA: { + RSA *rsa = RSA_parse_private_key(cbs); + if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) { + RSA_free(rsa); + goto err; + } + return ret; + } + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE); + goto err; + } + +err: + EVP_PKEY_free(ret); + return NULL; +} + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp, + long len) { + if (len < 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* Parse with the legacy format. */ + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EVP_PKEY *ret = old_priv_decode(&cbs, type); + if (ret == NULL) { + /* Try again with PKCS#8. */ + ERR_clear_error(); + CBS_init(&cbs, *inp, (size_t)len); + ret = EVP_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (ret->type != type) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); + EVP_PKEY_free(ret); + return NULL; + } + } + + if (out != NULL) { + EVP_PKEY_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +/* num_elements parses one SEQUENCE from |in| and returns the number of elements + * in it. On parse error, it returns zero. */ +static size_t num_elements(const uint8_t *in, size_t in_len) { + CBS cbs, sequence; + CBS_init(&cbs, in, (size_t)in_len); + + if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) { + return 0; + } + + size_t count = 0; + while (CBS_len(&sequence) > 0) { + if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) { + return 0; + } + + count++; + } + + return count; +} + +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) { + if (len < 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* Parse the input as a PKCS#8 PrivateKeyInfo. */ + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EVP_PKEY *ret = EVP_parse_private_key(&cbs); + if (ret != NULL) { + if (out != NULL) { + EVP_PKEY_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; + } + ERR_clear_error(); + + /* Count the elements to determine the legacy key format. */ + switch (num_elements(*inp, (size_t)len)) { + case 4: + return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len); + + case 6: + return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len); + + default: + return d2i_PrivateKey(EVP_PKEY_RSA, 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, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; + } +} diff --git a/external/boringssl/crypto/evp/evp_ctx.c b/external/boringssl/crypto/evp/evp_ctx.c new file mode 100644 index 0000000000..f510f6c7d8 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_ctx.c @@ -0,0 +1,445 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +#include "internal.h" + + +static const EVP_PKEY_METHOD *const evp_methods[] = { + &rsa_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_R_UNSUPPORTED_ALGORITHM); + ERR_add_error_dataf("algorithm %d", id); + return NULL; + } + + ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); + if (!ret) { + OPENSSL_PUT_ERROR(EVP, 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_up_ref(pkey); + } + + if (pmeth->init) { + if (pmeth->init(ret) <= 0) { + 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); + } + EVP_PKEY_free(ctx->pkey); + 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_up_ref(pctx->pkey); + if (rctx->pkey == NULL) { + goto err; + } + } + + if (pctx->peerkey) { + rctx->peerkey = EVP_PKEY_up_ref(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, ERR_LIB_EVP); + return NULL; +} + +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; } + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, + int p1, void *p2) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } + if (keytype != -1 && ctx->pmeth->pkey_id != keytype) { + return 0; + } + + if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_OPERATION_SET); + return 0; + } + + if (optype != -1 && !(ctx->operation & optype)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION); + return 0; + } + + return ctx->pmeth->ctrl(ctx, cmd, p1, p2); +} + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + ctx->operation = EVP_PKEY_OP_SIGN; + 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_SIGN) { + OPENSSL_PUT_ERROR(EVP, 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_VERIFY; + 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_VERIFY) { + OPENSSL_PUT_ERROR(EVP, 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_ENCRYPT; + 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { + OPENSSL_PUT_ERROR(EVP, 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_DECRYPT; + 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_DECRYPT) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); +} + +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_VERIFYRECOVER; + return 1; +} + +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, + const uint8_t *sig, size_t sig_len) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->verify_recover(ctx, out, out_len, sig, sig_len); +} + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_DERIVE; + 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_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_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_R_NO_KEY_SET); + return 0; + } + + if (ctx->pkey->type != peer->type) { + OPENSSL_PUT_ERROR(EVP, 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_R_DIFFERENT_PARAMETERS); + return 0; + } + + 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_up_ref(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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_DERIVE) { + OPENSSL_PUT_ERROR(EVP, 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_KEYGEN; + 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_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_KEYGEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + + if (!ppkey) { + return 0; + } + + if (!*ppkey) { + *ppkey = EVP_PKEY_new(); + if (!*ppkey) { + OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP); + return 0; + } + } + + if (!ctx->pmeth->keygen(ctx, *ppkey)) { + EVP_PKEY_free(*ppkey); + *ppkey = NULL; + return 0; + } + return 1; +} diff --git a/external/boringssl/crypto/evp/evp_extra_test.cc b/external/boringssl/crypto/evp/evp_extra_test.cc new file mode 100644 index 0000000000..9bc36ad886 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_extra_test.cc @@ -0,0 +1,721 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.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 kExampleDSAKeyDER[] = { + 0x30, 0x82, 0x03, 0x56, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0x9e, 0x12, 0xfa, 0xb3, 0xde, 0x12, 0x21, 0x35, 0x01, 0xdd, 0x82, 0xaa, + 0x10, 0xca, 0x2d, 0x10, 0x1d, 0x2d, 0x4e, 0xbf, 0xef, 0x4d, 0x2a, 0x3f, + 0x8d, 0xaa, 0x0f, 0xe0, 0xce, 0xda, 0xd8, 0xd6, 0xaf, 0x85, 0x61, 0x6a, + 0xa2, 0xf3, 0x25, 0x2c, 0x0a, 0x2b, 0x5a, 0x6d, 0xb0, 0x9e, 0x6f, 0x14, + 0x90, 0x0e, 0x0d, 0xdb, 0x83, 0x11, 0x87, 0x6d, 0xd8, 0xf9, 0x66, 0x95, + 0x25, 0xf9, 0x9e, 0xd6, 0x59, 0x49, 0xe1, 0x84, 0xd5, 0x06, 0x47, 0x93, + 0x27, 0x11, 0x69, 0xa2, 0x28, 0x68, 0x0b, 0x95, 0xec, 0x12, 0xf5, 0x9a, + 0x8e, 0x20, 0xb2, 0x1f, 0x2b, 0x58, 0xeb, 0x2a, 0x20, 0x12, 0xd3, 0x5b, + 0xde, 0x2e, 0xe3, 0x51, 0x82, 0x2f, 0xe8, 0xf3, 0x2d, 0x0a, 0x33, 0x05, + 0x65, 0xdc, 0xce, 0x5c, 0x67, 0x2b, 0x72, 0x59, 0xc1, 0x4b, 0x24, 0x33, + 0xd0, 0xb5, 0xb2, 0xca, 0x2b, 0x2d, 0xb0, 0xab, 0x62, 0x6e, 0x8f, 0x13, + 0xf4, 0x7f, 0xe0, 0x34, 0x5d, 0x90, 0x4e, 0x72, 0x94, 0xbb, 0x03, 0x8e, + 0x9c, 0xe2, 0x1a, 0x9e, 0x58, 0x0b, 0x83, 0x35, 0x62, 0x78, 0x70, 0x6c, + 0xfe, 0x76, 0x84, 0x36, 0xc6, 0x9d, 0xe1, 0x49, 0xcc, 0xff, 0x98, 0xb4, + 0xaa, 0xb8, 0xcb, 0x4f, 0x63, 0x85, 0xc9, 0xf1, 0x02, 0xce, 0x59, 0x34, + 0x6e, 0xae, 0xef, 0x27, 0xe0, 0xad, 0x22, 0x2d, 0x53, 0xd6, 0xe8, 0x9c, + 0xc8, 0xcd, 0xe5, 0x77, 0x6d, 0xd0, 0x00, 0x57, 0xb0, 0x3f, 0x2d, 0x88, + 0xab, 0x3c, 0xed, 0xba, 0xfd, 0x7b, 0x58, 0x5f, 0x0b, 0x7f, 0x78, 0x35, + 0xe1, 0x7a, 0x37, 0x28, 0xbb, 0xf2, 0x5e, 0xa6, 0x25, 0x72, 0xf2, 0x45, + 0xdc, 0x11, 0x1f, 0x3c, 0xe3, 0x9c, 0xb6, 0xff, 0xac, 0xc3, 0x1b, 0x0a, + 0x27, 0x90, 0xe7, 0xbd, 0xe9, 0x02, 0x24, 0xea, 0x9b, 0x09, 0x31, 0x53, + 0x62, 0xaf, 0x3d, 0x2b, 0x02, 0x21, 0x00, 0xf3, 0x81, 0xdc, 0xf5, 0x3e, + 0xbf, 0x72, 0x4f, 0x8b, 0x2e, 0x5c, 0xa8, 0x2c, 0x01, 0x0f, 0xb4, 0xb5, + 0xed, 0xa9, 0x35, 0x8d, 0x0f, 0xd8, 0x8e, 0xd2, 0x78, 0x58, 0x94, 0x88, + 0xb5, 0x4f, 0xc3, 0x02, 0x82, 0x01, 0x00, 0x0c, 0x40, 0x2a, 0x72, 0x5d, + 0xcc, 0x3a, 0x62, 0xe0, 0x2b, 0xf4, 0xcf, 0x43, 0xcd, 0x17, 0xf4, 0xa4, + 0x93, 0x59, 0x12, 0x20, 0x22, 0x36, 0x69, 0xcf, 0x41, 0x93, 0xed, 0xab, + 0x42, 0x3a, 0xd0, 0x8d, 0xfb, 0x55, 0x2e, 0x30, 0x8a, 0x6a, 0x57, 0xa5, + 0xff, 0xbc, 0x7c, 0xd0, 0xfb, 0x20, 0x87, 0xf8, 0x1f, 0x8d, 0xf0, 0xcb, + 0x08, 0xab, 0x21, 0x33, 0x28, 0x7d, 0x2b, 0x69, 0x68, 0x71, 0x4a, 0x94, + 0xf6, 0x33, 0xc9, 0x40, 0x84, 0x5a, 0x48, 0xa3, 0xe1, 0x67, 0x08, 0xdd, + 0xe7, 0x61, 0xcc, 0x6a, 0x8e, 0xab, 0x2d, 0x84, 0xdb, 0x21, 0xb6, 0xea, + 0x5b, 0x07, 0x68, 0x14, 0x93, 0xcc, 0x9c, 0x31, 0xfb, 0xc3, 0x68, 0xb2, + 0x43, 0xf6, 0xdd, 0xf8, 0xc9, 0x32, 0xa8, 0xb4, 0x03, 0x8f, 0x44, 0xe7, + 0xb1, 0x5c, 0xa8, 0x76, 0x34, 0x4a, 0x14, 0x78, 0x59, 0xf2, 0xb4, 0x3b, + 0x39, 0x45, 0x86, 0x68, 0xad, 0x5e, 0x0a, 0x1a, 0x9a, 0x66, 0x95, 0x46, + 0xdd, 0x28, 0x12, 0xe3, 0xb3, 0x61, 0x7a, 0x0a, 0xef, 0x99, 0xd5, 0x8e, + 0x3b, 0xb4, 0xcc, 0x87, 0xfd, 0x94, 0x22, 0x5e, 0x01, 0xd2, 0xdc, 0xc4, + 0x69, 0xa7, 0x72, 0x68, 0x14, 0x6c, 0x51, 0x91, 0x8f, 0x18, 0xe8, 0xb4, + 0xd7, 0x0a, 0xa1, 0xf0, 0xc7, 0x62, 0x3b, 0xcc, 0x52, 0xcf, 0x37, 0x31, + 0xd3, 0x86, 0x41, 0xb2, 0xd2, 0x83, 0x0b, 0x7e, 0xec, 0xb2, 0xf0, 0x95, + 0x52, 0xff, 0x13, 0x7d, 0x04, 0x6e, 0x49, 0x4e, 0x7f, 0x33, 0xc3, 0x59, + 0x00, 0x02, 0xb1, 0x6d, 0x1b, 0x97, 0xd9, 0x36, 0xfd, 0xa2, 0x8f, 0x90, + 0xc3, 0xed, 0x3c, 0xa3, 0x53, 0x38, 0x16, 0x8a, 0xc1, 0x6f, 0x77, 0xc3, + 0xc5, 0x7a, 0xdc, 0x2e, 0x8f, 0x7c, 0x6c, 0x22, 0x56, 0xe4, 0x1a, 0x5f, + 0x65, 0x45, 0x05, 0x90, 0xdb, 0xb5, 0xbc, 0xf0, 0x6d, 0x66, 0x61, 0x02, + 0x82, 0x01, 0x00, 0x31, 0x97, 0x31, 0xa1, 0x4e, 0x38, 0x56, 0x88, 0xdb, + 0x94, 0x1d, 0xbf, 0x65, 0x5c, 0xda, 0x4b, 0xc2, 0x10, 0xde, 0x74, 0x20, + 0x03, 0xce, 0x13, 0x60, 0xf2, 0x25, 0x1d, 0x55, 0x7c, 0x5d, 0x94, 0x82, + 0x54, 0x08, 0x53, 0xdb, 0x85, 0x95, 0xbf, 0xdd, 0x5e, 0x50, 0xd5, 0x96, + 0xe0, 0x79, 0x51, 0x1b, 0xbf, 0x4d, 0x4e, 0xb9, 0x3a, 0xc5, 0xee, 0xc4, + 0x5e, 0x98, 0x75, 0x7b, 0xbe, 0xff, 0x30, 0xe6, 0xd0, 0x7b, 0xa6, 0xf1, + 0xbc, 0x29, 0xea, 0xdf, 0xec, 0xf3, 0x8b, 0xfa, 0x83, 0x11, 0x9f, 0x3f, + 0xf0, 0x5d, 0x06, 0x51, 0x32, 0xaa, 0x21, 0xfc, 0x26, 0x17, 0xe7, 0x50, + 0xc2, 0x16, 0xba, 0xfa, 0x54, 0xb7, 0x7e, 0x1d, 0x2c, 0xa6, 0xa3, 0x41, + 0x66, 0x33, 0x94, 0x83, 0xb9, 0xbf, 0xa0, 0x4f, 0xbd, 0xa6, 0xfd, 0x2c, + 0x81, 0x58, 0x35, 0x33, 0x39, 0xc0, 0x6d, 0x33, 0x40, 0x56, 0x64, 0x12, + 0x5a, 0xcd, 0x35, 0x53, 0x21, 0x78, 0x8f, 0x27, 0x24, 0x37, 0x66, 0x8a, + 0xdf, 0x5e, 0x5f, 0x63, 0xfc, 0x8b, 0x2d, 0xef, 0x57, 0xdb, 0x40, 0x25, + 0xd5, 0x17, 0x53, 0x0b, 0xe4, 0xa5, 0xae, 0x54, 0xbf, 0x46, 0x4f, 0xa6, + 0x79, 0xc3, 0x74, 0xfa, 0x1f, 0x85, 0x34, 0x64, 0x6d, 0xc5, 0x03, 0xeb, + 0x72, 0x98, 0x80, 0x7b, 0xc0, 0x8f, 0x35, 0x11, 0xa7, 0x09, 0xeb, 0x51, + 0xe0, 0xb0, 0xac, 0x92, 0x14, 0xf2, 0xad, 0x37, 0x95, 0x5a, 0xba, 0x8c, + 0xc4, 0xdb, 0xed, 0xc4, 0x4e, 0x8b, 0x8f, 0x84, 0x33, 0x64, 0xf8, 0x57, + 0x12, 0xd7, 0x08, 0x7e, 0x90, 0x66, 0xdf, 0x91, 0x50, 0x23, 0xf2, 0x73, + 0xc0, 0x6b, 0xb1, 0x15, 0xdd, 0x64, 0xd7, 0xc9, 0x75, 0x17, 0x73, 0x72, + 0xda, 0x33, 0xc4, 0x6f, 0xa5, 0x47, 0xa1, 0xcc, 0xd1, 0xc6, 0x62, 0xe5, + 0xca, 0xab, 0x5f, 0x2a, 0x8f, 0x6b, 0xcc, 0x02, 0x21, 0x00, 0xb0, 0xc7, + 0x68, 0x70, 0x27, 0x43, 0xbc, 0x51, 0x24, 0x29, 0x93, 0xa9, 0x71, 0xa5, + 0x28, 0x89, 0x79, 0x54, 0x44, 0xf7, 0xc6, 0x45, 0x22, 0x03, 0xd0, 0xce, + 0x84, 0xfe, 0x61, 0x17, 0xd4, 0x6e, +}; + +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, +}; + +// 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, +}; + +// kExampleECKeyPKCS8 is a sample EC private key encoded as a PKCS#8 +// PrivateKeyInfo. +static const uint8_t kExampleECKeyPKCS8[] = { + 0x30, 0x81, 0x87, 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, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, 0xfa, 0x16, 0xdf, + 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, 0x91, 0x95, 0xab, + 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, 0x44, 0x03, 0x42, + 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, 0x37, 0x9a, 0xd5, + 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, 0x20, 0xcb, 0x90, + 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, 0xc0, 0xdb, 0xba, + 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73, + 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7, + 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec, +}; + +// kExampleECKeySpecifiedCurvePKCS8 is a sample EC private key encoded as a +// PKCS#8 PrivateKeyInfo with P-256's parameters spelled out rather than using +// the curve OID. +static const uint8_t kExampleECKeySpecifiedCurvePKCS8[] = { + 0x30, 0x82, 0x01, 0x79, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x03, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02, + 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, + 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, + 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, + 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, + 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, + 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, + 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, + 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, + 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, + 0x01, 0x04, 0x20, 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, + 0xfa, 0x16, 0xdf, 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, + 0x91, 0x95, 0xab, 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, + 0x44, 0x03, 0x42, 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, + 0x37, 0x9a, 0xd5, 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, + 0x20, 0xcb, 0x90, 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, + 0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, + 0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, + 0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec, +}; + +// 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 +}; + +// kExampleBadECKeyDER2 is a sample EC private key encoded as an ECPrivateKey +// structure, but with the curve OID swapped out for 1.1.1.1.1.1.1.1.1. It is +// then concatenated with an ECPrivateKey wrapped in a PrivateKeyInfo, +// optional public key omitted, and with the private key chopped off. +static const uint8_t kExampleBadECKeyDER2[] = { + 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, 0x29, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 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, 0x30, 0x41, 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, 0x27, 0x30, 0x25, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x07, +}; + +// kInvalidPrivateKey is an invalid private key. See +// https://rt.openssl.org/Ticket/Display.html?id=4131. +static const uint8_t kInvalidPrivateKey[] = { + 0x30, 0x39, 0x02, 0x01, 0x02, 0x30, 0x09, 0x06, 0x01, 0x38, 0x08, + 0x04, 0x69, 0x30, 0x30, 0x80, 0x30, 0x19, 0x01, 0x02, 0x9f, 0xf8, + 0x8b, 0x29, 0x80, 0x30, 0xb0, 0x1b, 0x06, 0x09, 0x22, 0xbe, 0x08, + 0x04, 0xe9, 0x30, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x3a, 0x01, 0x80, + 0x09, 0x30, 0x80, 0x06, 0x01, 0x02, 0x30, 0x80, 0x30, 0x01, 0x3b, + 0x02, 0x00, 0x00, 0x04, 0x20, 0x30, 0x82, 0x04, 0xe9, 0x30, 0xc3, + 0xe8, 0x30, 0x01, 0x05, 0x30, 0x80, 0x30, 0x01, 0x3b, 0x01, 0x04, + 0x02, 0x02, 0xff, 0x00, 0x30, 0x29, 0x02, 0x11, 0x03, 0x29, 0x29, + 0x02, 0x00, 0x99, 0x30, 0x80, 0x06, 0x21, 0x02, 0x24, 0x04, 0xe8, + 0x30, 0x01, 0x01, 0x04, 0x30, 0x80, 0x1b, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x30, 0x01, 0xaa, 0x02, 0x86, 0xc0, 0x30, 0xdf, 0xe9, 0x80, +}; + +static ScopedEVP_PKEY LoadExampleRSAKey() { + ScopedRSA rsa(RSA_private_key_from_bytes(kExampleRSAKeyDER, + sizeof(kExampleRSAKeyDER))); + if (!rsa) { + return nullptr; + } + ScopedEVP_PKEY pkey(EVP_PKEY_new()); + if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) { + return nullptr; + } + return pkey; +} + +static bool TestEVP_DigestSignInit(void) { + ScopedEVP_PKEY pkey = LoadExampleRSAKey(); + ScopedEVP_MD_CTX md_ctx; + if (!pkey || + !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) || + !EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) { + return false; + } + // Determine the size of the signature. + size_t sig_len = 0; + if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) { + return false; + } + // Sanity check for testing. + if (sig_len != (size_t)EVP_PKEY_size(pkey.get())) { + fprintf(stderr, "sig_len mismatch\n"); + return false; + } + + std::vector sig; + sig.resize(sig_len); + if (!EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len)) { + return false; + } + sig.resize(sig_len); + + // Ensure that the signature round-trips. + md_ctx.Reset(); + if (!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, + pkey.get()) || + !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) || + !EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len)) { + return false; + } + + return true; +} + +static bool TestEVP_DigestVerifyInit(void) { + ScopedEVP_PKEY pkey = LoadExampleRSAKey(); + ScopedEVP_MD_CTX md_ctx; + if (!pkey || + !EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, + pkey.get()) || + !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) || + !EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature))) { + return false; + } + return true; +} + +static bool TestVerifyRecover() { + ScopedEVP_PKEY pkey = LoadExampleRSAKey(); + if (!pkey) { + return false; + } + + ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); + if (!rsa) { + return false; + } + + const uint8_t kDummyHash[32] = {0}; + uint8_t sig[2048/8]; + unsigned sig_len = sizeof(sig); + + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig, &sig_len, + rsa.get())) { + fprintf(stderr, "RSA_sign failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + size_t out_len; + ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); + if (!EVP_PKEY_verify_recover_init(ctx.get()) || + !EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) || + !EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()) || + !EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len)) { + fprintf(stderr, "verify_recover failed will nullptr buffer.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + std::vector recovered; + recovered.resize(out_len); + + if (!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig, + sig_len)) { + fprintf(stderr, "verify_recover failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (out_len != sizeof(kDummyHash)) { + fprintf(stderr, "verify_recover length is %u, expected %u.\n", + static_cast(out_len), + static_cast(sizeof(kDummyHash))); + return false; + } + + if (memcmp(recovered.data(), kDummyHash, sizeof(kDummyHash)) != 0) { + fprintf(stderr, "verify_recover got wrong value.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + out_len = recovered.size(); + if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr) || + !EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig, + sig_len)) { + fprintf(stderr, "verify_recover failed with NULL MD.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + /* The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51 + * bytes. */ + static const size_t kExpectedASN1Size = 51; + if (out_len != kExpectedASN1Size) { + fprintf(stderr, "verify_recover length without MD is %u, expected %u.\n", + static_cast(out_len), + static_cast(kExpectedASN1Size)); + return false; + } + + return true; +} + +static bool TestValidPrivateKey(const uint8_t *input, size_t input_len, + int expected_id) { + const uint8_t *p = input; + ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, input_len)); + if (!pkey || p != input + input_len) { + fprintf(stderr, "d2i_AutoPrivateKey failed\n"); + return false; + } + + if (EVP_PKEY_id(pkey.get()) != expected_id) { + fprintf(stderr, "Did not decode expected type\n"); + return false; + } + + return true; +} + +static bool Testd2i_AutoPrivateKey() { + if (!TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER), + EVP_PKEY_RSA)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8), + EVP_PKEY_RSA)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER), + EVP_PKEY_EC)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8), + EVP_PKEY_EC)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyPKCS8) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8, + sizeof(kExampleECKeySpecifiedCurvePKCS8), + EVP_PKEY_EC)) { + fprintf(stderr, + "d2i_AutoPrivateKey(kExampleECKeySpecifiedCurvePKCS8) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER), + EVP_PKEY_DSA)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n"); + return false; + } + + const uint8_t *p = kInvalidPrivateKey; + ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey))); + if (pkey) { + fprintf(stderr, "Parsed invalid private key\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +// TestEVP_PKCS82PKEY tests loading a bad key in PKCS8 format. +static bool TestEVP_PKCS82PKEY(void) { + const uint8_t *derp = kExampleBadECKeyDER; + ScopedPKCS8_PRIV_KEY_INFO p8inf( + d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER))); + if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) { + fprintf(stderr, "Failed to parse key\n"); + return false; + } + + ScopedEVP_PKEY pkey(EVP_PKCS82PKEY(p8inf.get())); + if (pkey) { + fprintf(stderr, "Imported invalid EC key\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +// TestEVPMarshalEmptyPublicKey tests |EVP_marshal_public_key| on an empty key. +static bool TestEVPMarshalEmptyPublicKey(void) { + ScopedEVP_PKEY empty(EVP_PKEY_new()); + if (!empty) { + return false; + } + ScopedCBB cbb; + if (EVP_marshal_public_key(cbb.get(), empty.get())) { + fprintf(stderr, "Marshalled empty public key.\n"); + return false; + } + if (ERR_GET_REASON(ERR_peek_last_error()) != EVP_R_UNSUPPORTED_ALGORITHM) { + fprintf(stderr, "Marshalling an empty public key gave wrong error.\n"); + return false; + } + ERR_clear_error(); + return true; +} + +// Testd2i_PrivateKey tests |d2i_PrivateKey|. +static bool Testd2i_PrivateKey(void) { + const uint8_t *derp = kExampleRSAKeyDER; + ScopedEVP_PKEY pkey(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp, + sizeof(kExampleRSAKeyDER))); + if (!pkey || derp != kExampleRSAKeyDER + sizeof(kExampleRSAKeyDER)) { + fprintf(stderr, "Failed to import raw RSA key.\n"); + return false; + } + + derp = kExampleDSAKeyDER; + pkey.reset(d2i_PrivateKey(EVP_PKEY_DSA, nullptr, &derp, + sizeof(kExampleDSAKeyDER))); + if (!pkey || derp != kExampleDSAKeyDER + sizeof(kExampleDSAKeyDER)) { + fprintf(stderr, "Failed to import raw DSA key.\n"); + return false; + } + + derp = kExampleRSAKeyPKCS8; + pkey.reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp, + sizeof(kExampleRSAKeyPKCS8))); + if (!pkey || derp != kExampleRSAKeyPKCS8 + sizeof(kExampleRSAKeyPKCS8)) { + fprintf(stderr, "Failed to import PKCS#8 RSA key.\n"); + return false; + } + + derp = kExampleECKeyDER; + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, + sizeof(kExampleECKeyDER))); + if (!pkey || derp != kExampleECKeyDER + sizeof(kExampleECKeyDER)) { + fprintf(stderr, "Failed to import raw EC key.\n"); + return false; + } + + derp = kExampleBadECKeyDER; + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, + sizeof(kExampleBadECKeyDER))); + if (pkey) { + fprintf(stderr, "Imported invalid EC key.\n"); + return false; + } + ERR_clear_error(); + + // Copy the input into a |malloc|'d vector to flag memory errors. + std::vector copy(kExampleBadECKeyDER2, kExampleBadECKeyDER2 + + sizeof(kExampleBadECKeyDER2)); + derp = copy.data(); + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, copy.size())); + if (pkey) { + fprintf(stderr, "Imported invalid EC key #2.\n"); + return false; + } + ERR_clear_error(); + + derp = kExampleRSAKeyPKCS8; + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, + sizeof(kExampleRSAKeyPKCS8))); + if (pkey) { + fprintf(stderr, "Imported RSA key as EC key.\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestEVP_DigestSignInit()) { + fprintf(stderr, "EVP_DigestSignInit failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestEVP_DigestVerifyInit()) { + fprintf(stderr, "EVP_DigestVerifyInit failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestVerifyRecover()) { + fprintf(stderr, "EVP_PKEY_verify_recover failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!Testd2i_AutoPrivateKey()) { + fprintf(stderr, "Testd2i_AutoPrivateKey failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestEVP_PKCS82PKEY()) { + fprintf(stderr, "TestEVP_PKCS82PKEY failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestEVPMarshalEmptyPublicKey()) { + fprintf(stderr, "TestEVPMarshalEmptyPublicKey failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!Testd2i_PrivateKey()) { + fprintf(stderr, "Testd2i_PrivateKey failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/evp/evp_test.cc b/external/boringssl/crypto/evp/evp_test.cc new file mode 100644 index 0000000000..b01d1e47a1 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_test.cc @@ -0,0 +1,265 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2015 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include + +#include +#include +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(push)) +OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) + +#include +#include +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#include +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +// evp_test dispatches between multiple test types. PrivateKey tests take a key +// name parameter and single block, decode it as a PEM private key, and save it +// under that key name. Decrypt, Sign, and Verify tests take a previously +// imported key name as parameter and test their respective operations. + +static const EVP_MD *GetDigest(FileTest *t, const std::string &name) { + if (name == "MD5") { + return EVP_md5(); + } else if (name == "SHA1") { + return EVP_sha1(); + } else if (name == "SHA224") { + return EVP_sha224(); + } else if (name == "SHA256") { + return EVP_sha256(); + } else if (name == "SHA384") { + return EVP_sha384(); + } else if (name == "SHA512") { + return EVP_sha512(); + } + t->PrintLine("Unknown digest: '%s'", name.c_str()); + return nullptr; +} + +static int GetKeyType(FileTest *t, const std::string &name) { + if (name == "RSA") { + return EVP_PKEY_RSA; + } + if (name == "EC") { + return EVP_PKEY_EC; + } + if (name == "DSA") { + return EVP_PKEY_DSA; + } + t->PrintLine("Unknown key type: '%s'", name.c_str()); + return EVP_PKEY_NONE; +} + +using KeyMap = std::map; + +static bool ImportKey(FileTest *t, KeyMap *key_map, + EVP_PKEY *(*parse_func)(CBS *cbs), + int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) { + std::vector input; + if (!t->GetBytes(&input, "Input")) { + return false; + } + + CBS cbs; + CBS_init(&cbs, input.data(), input.size()); + ScopedEVP_PKEY pkey(parse_func(&cbs)); + if (!pkey) { + return false; + } + + std::string key_type; + if (!t->GetAttribute(&key_type, "Type")) { + return false; + } + if (EVP_PKEY_id(pkey.get()) != GetKeyType(t, key_type)) { + t->PrintLine("Bad key type."); + return false; + } + + // The key must re-encode correctly. + ScopedCBB cbb; + uint8_t *der; + size_t der_len; + if (!CBB_init(cbb.get(), 0) || + !marshal_func(cbb.get(), pkey.get()) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + ScopedOpenSSLBytes free_der(der); + + std::vector output = input; + if (t->HasAttribute("Output") && + !t->GetBytes(&output, "Output")) { + return false; + } + if (!t->ExpectBytesEqual(output.data(), output.size(), der, der_len)) { + t->PrintLine("Re-encoding the key did not match."); + return false; + } + + // Save the key for future tests. + const std::string &key_name = t->GetParameter(); + if (key_map->count(key_name) > 0) { + t->PrintLine("Duplicate key '%s'.", key_name.c_str()); + return false; + } + (*key_map)[key_name] = std::move(pkey); + return true; +} + +static bool TestEVP(FileTest *t, void *arg) { + KeyMap *key_map = reinterpret_cast(arg); + if (t->GetType() == "PrivateKey") { + return ImportKey(t, key_map, EVP_parse_private_key, + EVP_marshal_private_key); + } + + if (t->GetType() == "PublicKey") { + return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key); + } + + int (*key_op_init)(EVP_PKEY_CTX *ctx); + int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, + const uint8_t *in, size_t in_len); + if (t->GetType() == "Decrypt") { + key_op_init = EVP_PKEY_decrypt_init; + key_op = EVP_PKEY_decrypt; + } else if (t->GetType() == "Sign") { + key_op_init = EVP_PKEY_sign_init; + key_op = EVP_PKEY_sign; + } else if (t->GetType() == "Verify") { + key_op_init = EVP_PKEY_verify_init; + key_op = nullptr; // EVP_PKEY_verify is handled differently. + } else { + t->PrintLine("Unknown test '%s'", t->GetType().c_str()); + return false; + } + + // Load the key. + const std::string &key_name = t->GetParameter(); + if (key_map->count(key_name) == 0) { + t->PrintLine("Could not find key '%s'.", key_name.c_str()); + return false; + } + EVP_PKEY *key = (*key_map)[key_name].get(); + + std::vector input, output; + if (!t->GetBytes(&input, "Input") || + !t->GetBytes(&output, "Output")) { + return false; + } + + // Set up the EVP_PKEY_CTX. + ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(key, nullptr)); + if (!ctx || !key_op_init(ctx.get())) { + return false; + } + if (t->HasAttribute("Digest")) { + const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("Digest")); + if (digest == nullptr || + !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) { + return false; + } + } + + if (t->GetType() == "Verify") { + if (!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(), + input.size())) { + // ECDSA sometimes doesn't push an error code. Push one on the error queue + // so it's distinguishable from other errors. + OPENSSL_PUT_ERROR(USER, ERR_R_EVP_LIB); + return false; + } + return true; + } + + size_t len; + std::vector actual; + if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) { + return false; + } + actual.resize(len); + if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) { + return false; + } + actual.resize(len); + if (!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) { + return false; + } + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + KeyMap map; + return FileTestMain(TestEVP, &map, argv[1]); +} diff --git a/external/boringssl/crypto/evp/evp_tests.txt b/external/boringssl/crypto/evp/evp_tests.txt new file mode 100644 index 0000000000..7c316d8146 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_tests.txt @@ -0,0 +1,215 @@ +# Public key algorithm tests + +# Keys used for PKEY operations. + +# RSA 2048 bit key. +PrivateKey = RSA-2048 +Type = RSA +Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f02030100010282010060297ac7991b167a06d6b24758b8cbe208beb9b2d9ec9738bd80f90a2e35005dd7ce292d9e29ba885bd316fef1f20913bc0ac90d6b0808b2414d82104441d8624a33ce0233c8f780a48b375aff02d76712228a702484db3f9ebecccfbbee1709dba182800d949e9e4216e0bff3558388f8bd90da373a1d82743ec3fbdd1427fd16825a657a316912e8695365117ca2f845c909405fcac55f895fc15d20386c26ee78c9e99075029a178a6c1e4cf0c200e8a9cfb27e9d156f86e6c2adc22b1a84a1cd5ca5b2790875d79407c84b352395cb81cc3fed5bb043b69ede0c07204550025cee8c5f440170b6120bb48e0f747bcd8f522110850df043c428dfd187053102818100f6f961b47cbc035d3aedebc7de850a956b65ecdb9cf60764063f15aa48553c58d972fe6675056e35ddfdc37bf3b9f2f622ee271337256849c9bef2176fe8f7c3f8bb91ba374dd53baf3dec814d2bdec10c1fdc88cdd16876f26b1edfa3f094197edf4d42ff1fb2971103b898ca859c427287086a842ab410bb69cf2d35af6be302818100d47e724a7ff41048b270c2524a4101878b73159bb73d3dbc187b220e635b3534f96e243a184d93f860b6bfbb6b71c1ed9a1e1f458583023c301e96a692c1a08b53d0ec9ca910100d80451e3b7dc6a01bac4aecef8df798846bc235a08cbba2cf4c06804cc11219e95608c714e3f1430d491fadbba32a5751a04f97745834c9a502818021f2452bb9b95dfd028c914bf799f1ca77e89a95d50d3c16d384f8455f8bd7af9eb3dfa3d591d9842def235f7630a8e48c088ff6642e101794535a933e1e976fa8509fc728b2da0c4a1a08d7fcf37abaae1ff3001aca1dc1bbb05d9dffbaa1a09f7fb1eef38237d9ebccc722b9338436dde7119112798c26809c1a8dec4320610281801f7510aa62c2d8de4a3c53282781f41e02d0e8b402ae78432e449c48110161a11403f02d01880a8dcc938152d79721a4711a607ac4471ebf964810f95be47a45e60499e29f4c9773c83773404f606637728c2d0351bb03c326c8bb73a721e7fa5440ea2172bba1465fcc30dcb0d9f89930e815aa1f7f9729a857e00e0338dd590281804d1f0d756fe77e01099a652f50a88b7b685dc5bf00981d5d2376fd0c6fe29cd5b638734479305a73ad3c1599d39eae3bae035fbd6fed07c28de705933879a06e48e6a603686ed8e2560a5f6af1f2c24faf4aa960e382186f15eedce9a2491ae730680dd4cf778b70faa86826ab3223477cc91377b19a6d5a2eaea219760beed5 + +# The public half of the same key encoded as a SubjectPublicKeyInfo. +PublicKey = RSA-2048-SPKI +Type = RSA +Input = 30820122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001 + +# The same key but with missing parameters rather than a NULL. +PublicKey = RSA-2048-SPKI-Invalid +Input = 30820120300b06092a864886f70d0101010382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001 +Error = DECODE_ERROR + +# The same key but with an incorrectly-encoded length prefix. +PublicKey = RSA-2048-SPKI-Invalid2 +Input = 3083000122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001 +Error = DECODE_ERROR + +# EC P-256 key +PrivateKey = P-256 +Type = EC +Input = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 + +# The same key as above with the optional public key omitted. +PrivateKey = P-256-MissingPublic +Type = EC +Input = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725 + +# The same key as above with redundant parameters. +PrivateKey = P-256-ExtraParameters +Type = EC +Input = 308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00a06082a8648ce3d030107a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +# The key re-encodes with the parameters removed. +Output = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 + +# The same key, but with the redundant parameters in the ECPrivateKey mismatched. +PrivateKey = P-256-BadInnerParameters +Input = 308190020100301306072a8648ce3d020106082a8648ce3d0301070476307402010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00706052b81040022a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +Error = GROUP_MISMATCH + +# The public half of the same key encoded as a PublicKey. +PublicKey = P-256-SPKI +Type = EC +Input = 3059301306072a8648ce3d020106082a8648ce3d030107034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 + +# The same as above, but with the curve explicitly spelled out. +PublicKey = P-256-SPKI +Input = 3082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +Error = DECODE_ERROR + +# The same as above, but with trailing data after the curve name. +PublicKey = P-256-SPKI +Input = 305b301506072a8648ce3d020106082a8648ce3d0301070500034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +Error = DECODE_ERROR + +# A DSA private key. +PrivateKey = DSA-1024 +Type = DSA +Input = 308202650201003082023906072a8648ce3804013082022c02820101009e12fab3de12213501dd82aa10ca2d101d2d4ebfef4d2a3f8daa0fe0cedad8d6af85616aa2f3252c0a2b5a6db09e6f14900e0ddb8311876dd8f9669525f99ed65949e184d5064793271169a228680b95ec12f59a8e20b21f2b58eb2a2012d35bde2ee351822fe8f32d0a330565dcce5c672b7259c14b2433d0b5b2ca2b2db0ab626e8f13f47fe0345d904e7294bb038e9ce21a9e580b83356278706cfe768436c69de149ccff98b4aab8cb4f6385c9f102ce59346eaeef27e0ad222d53d6e89cc8cde5776dd00057b03f2d88ab3cedbafd7b585f0b7f7835e17a3728bbf25ea62572f245dc111f3ce39cb6ffacc31b0a2790e7bde90224ea9b09315362af3d2b022100f381dcf53ebf724f8b2e5ca82c010fb4b5eda9358d0fd88ed278589488b54fc3028201000c402a725dcc3a62e02bf4cf43cd17f4a493591220223669cf4193edab423ad08dfb552e308a6a57a5ffbc7cd0fb2087f81f8df0cb08ab2133287d2b6968714a94f633c940845a48a3e16708dde761cc6a8eab2d84db21b6ea5b07681493cc9c31fbc368b243f6ddf8c932a8b4038f44e7b15ca876344a147859f2b43b39458668ad5e0a1a9a669546dd2812e3b3617a0aef99d58e3bb4cc87fd94225e01d2dcc469a77268146c51918f18e8b4d70aa1f0c7623bcc52cf3731d38641b2d2830b7eecb2f09552ff137d046e494e7f33c3590002b16d1b97d936fda28f90c3ed3ca35338168ac16f77c3c57adc2e8f7c6c2256e41a5f65450590dbb5bcf06d66610423022100b0c768702743bc51242993a971a52889795444f7c6452203d0ce84fe6117d46e + +# A DSA public key. +PublicKey = DSA-1024-SPKI +Type = DSA +Input = 308201b73082012c06072a8648ce3804013082011f02818100b3429b8b128c9079f9b72e86857e98d265e5d91661ed8b5f4cc56e5eed1e571da30186983a9dd76297eab73ee13a1db841f8800d04a7cab478af6cde2ea4a2868531af169a24858c6268efa39ceb7ed0d4227eb5bbb01124a2a5a26038c7bcfb8cc827f68f5202345166e4718596799b65c9def82828ce44e62e38e41a0d24b1021500c5a56c81ddd87f47e676546c56d05706421624cf0281810094de40d27314fe929e47ff9b1ac65cfc73ef38c4d381c890be6217b15039ae18190e6b421af8c0bda35a5cfd050f58ae2644adce83e68c8e5ba11729df56bbb21e227a60b816cc033fa799a38fe1ba5b4aa1801b6f841ce3df99feb3b4fb96950c960af13fa2ce920aabc12dd24ad2044a35063ea0e25f67f560f4cfbdc5598303818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a + +# The same key as above, but without the parameters. +PublicKey = DSA-1024-SPKI-No-Params +Type = DSA +Input = 308192300906072a8648ce38040103818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a + + +# RSA tests + +Sign = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +Verify = RSA-2048-SPKI +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +# Digest too long +Sign = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF12345" +Output = +Error = INVALID_DIGEST_LENGTH + +# Digest too short +Sign = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF12345" +Output = +Error = INVALID_DIGEST_LENGTH + +# Mismatched digest +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1233" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad +Error = BAD_SIGNATURE + +# Corrupted signature +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1233" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ae +Error = BLOCK_TYPE_IS_NOT_01 + +# parameter missing (NOTE: this differs from upstream) +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3ec3fc29eb6e122bd7aa361cd09fe1bcbe85311096a7b9e4799cedfb2351ce0ab7fe4e75b4f6b37f67edd9c60c800f9ab941c0c157d7d880ca9de40c951d60fd293ae220d4bc510b1572d6e85a1bbbd8605b52e05f1c64fafdae59a1c2fbed214b7844d0134619de62851d5a0522e32e556e5950f3f97b8150e3f0dffee612c924201c27cd9bc8b423a71533380c276d3d59fcba35a2e80a1a192ec266a6c2255012cd86a349fe90a542b355fa3355b04da6cdf1df77f0e7bd44a90e880e1760266d233e465226f5db1c68857847d82072861ee266ddfc2e596845b77e1803274a579835ab5e4975d81d20b7df9cec7795489e4a2bdb8c1cf6a6b359945ac92c +Error = BAD_SIGNATURE + +# embedded digest too long +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d +Error = BAD_SIGNATURE + +# embedded digest too short +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d +Error = BAD_SIGNATURE + +# Garbage after DigestInfo +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 9ee34872d4271a7d8808af0a4052a145a6d6a8437d00da3ed14428c7f087cd39f4d43334c41af63e7fa1ba363fee7bcef401d9d36a662abbab55ce89a696e1be0dfa19a5d09ca617dd488787b6048baaefeb29bc8688b2fe3882de2b77c905b5a8b56cf9616041e5ec934ba6de863efe93acc4eef783fe7f72a00fa65d6093ed32bf98ce527e62ccb1d56317f4be18b7e0f55d7c36617d2d0678a306e3350956b662ac15df45215dd8f6b314babb9788e6c272fa461e4c9b512a11a4b92bc77c3a4c95c903fccb238794eca5c750477bf56ea6ee6a167367d881b485ae3889e7c489af8fdf38e0c0f2aed780831182e34abedd43c39281b290774bf35cc25274 +Error = BAD_SIGNATURE + +# invalid tag for parameter +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 49525db4d44c755e560cba980b1d85ea604b0e077fcadd4ba44072a3487bbddb835016200a7d8739cce2dc3223d9c20cbdd25059ab02277f1f21318efd18e21038ec89aa9d40680987129e8b41ba33bceb86518bdf47268b921cce2037acabca6575d832499538d6f40cdba0d40bd7f4d8ea6ca6e2eec87f294efc971407857f5d7db09f6a7b31e301f571c6d82a5e3d08d2bb3a36e673d28b910f5bec57f0fcc4d968fd7c94d0b9226dec17f5192ad8b42bcab6f26e1bea1fdc3b958199acb00f14ebcb2a352f3afcedd4c09000128a603bbeb9696dea13040445253972d46237a25c7845e3b464e6984c2348ea1f1210a9ff0b00d2d72b50db00c009bb39f9 +Error = BAD_SIGNATURE + +# EC tests + +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 + +Verify = P-256-SPKI +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 + +# Digest too long +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF12345" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Digest too short +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF123" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Digest invalid +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1235" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Invalid signature +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec7 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Garbage after signature +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec800 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = BAD_SIGNATURE + +# BER signature +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000 +Error = BAD_SIGNATURE diff --git a/external/boringssl/crypto/evp/internal.h b/external/boringssl/crypto/evp/internal.h new file mode 100644 index 0000000000..0783143d39 --- /dev/null +++ b/external/boringssl/crypto/evp/internal.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_EVP_INTERNAL_H +#define OPENSSL_HEADER_EVP_INTERNAL_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +struct evp_pkey_asn1_method_st { + int pkey_id; + uint8_t oid[9]; + uint8_t oid_len; + + /* pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo + * and writes the result into |out|. It returns one on success and zero on + * error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER + * type field, and |key| is the contents of the subjectPublicKey with the + * leading padding byte checked and removed. Although X.509 uses BIT STRINGs + * to represent SubjectPublicKeyInfo, every key type defined encodes the key + * as a byte string with the same conversion to BIT STRING. */ + int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key); + + /* pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result + * to |out|. It returns one on success and zero on error. */ + int (*pub_encode)(CBB *out, const EVP_PKEY *key); + + int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); + + /* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the + * result into |out|. It returns one on success and zero on error. |params| is + * the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key| + * is the contents of the OCTET STRING privateKey field. */ + int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key); + + /* priv_encode encodes |key| as a PrivateKeyInfo and appends the result to + * |out|. It returns one on success and zero on error. */ + int (*priv_encode)(CBB *out, const EVP_PKEY *key); + + /* 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_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); + + void (*pkey_free)(EVP_PKEY *pkey); +} /* EVP_PKEY_ASN1_METHOD */; + + +#define EVP_PKEY_OP_UNDEFINED 0 +#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_ENCRYPT (1 << 6) +#define EVP_PKEY_OP_DECRYPT (1 << 7) +#define EVP_PKEY_OP_DERIVE (1 << 8) + +#define EVP_PKEY_OP_TYPE_SIG \ + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER) + +#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_KEYGEN + +/* 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 one on success and zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2); + +#define EVP_PKEY_CTRL_MD 1 +#define EVP_PKEY_CTRL_GET_MD 2 + +/* 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 3 + +/* EVP_PKEY_ALG_CTRL is the base value from which key-type specific ctrl + * commands are numbered. */ +#define EVP_PKEY_ALG_CTRL 0x1000 + +#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; +} /* EVP_PKEY_CTX */; + +struct evp_pkey_method_st { + int pkey_id; + + int (*init)(EVP_PKEY_CTX *ctx); + int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src); + void (*cleanup)(EVP_PKEY_CTX *ctx); + + int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + + int (*sign)(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, + const uint8_t *tbs, size_t tbslen); + + int (*verify)(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, + const uint8_t *tbs, size_t tbslen); + + int (*verify_recover)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, + const uint8_t *sig, size_t sig_len); + + int (*encrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, + const uint8_t *in, size_t inlen); + + int (*decrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, + const uint8_t *in, size_t inlen); + + int (*derive)(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *keylen); + + int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2); +} /* EVP_PKEY_METHOD */; + +extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth; + +extern const EVP_PKEY_METHOD rsa_pkey_meth; +extern const EVP_PKEY_METHOD ec_pkey_meth; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_EVP_INTERNAL_H */ diff --git a/external/boringssl/crypto/evp/p_dsa_asn1.c b/external/boringssl/crypto/evp/p_dsa_asn1.c new file mode 100644 index 0000000000..1f022f1a81 --- /dev/null +++ b/external/boringssl/crypto/evp/p_dsa_asn1.c @@ -0,0 +1,268 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 3279, section 2.3.2. */ + + /* Parameters may or may not be present. */ + DSA *dsa; + if (CBS_len(params) == 0) { + dsa = DSA_new(); + if (dsa == NULL) { + return 0; + } + } else { + dsa = DSA_parse_parameters(params); + if (dsa == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + } + + dsa->pub_key = BN_new(); + if (dsa->pub_key == NULL) { + goto err; + } + + if (!BN_parse_asn1_unsigned(key, dsa->pub_key) || + CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + EVP_PKEY_assign_DSA(out, dsa); + return 1; + +err: + DSA_free(dsa); + return 0; +} + +static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) { + const DSA *dsa = key->pkey.dsa; + const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL; + + /* See RFC 5480, section 2. */ + CBB spki, algorithm, oid, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) || + (has_params && + !DSA_marshal_parameters(&algorithm, dsa)) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !BN_marshal_asn1(&key_bitstring, dsa->pub_key) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See PKCS#11, v2.40, section 2.5. */ + + /* Decode parameters. */ + BN_CTX *ctx = NULL; + DSA *dsa = DSA_parse_parameters(params); + if (dsa == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + dsa->priv_key = BN_new(); + dsa->pub_key = BN_new(); + if (dsa->priv_key == NULL || dsa->pub_key == NULL) { + goto err; + } + + /* Decode the key. */ + if (!BN_parse_asn1_unsigned(key, dsa->priv_key) || + CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + /* Calculate the public key. */ + ctx = BN_CTX_new(); + if (ctx == NULL || + !BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { + goto err; + } + + BN_CTX_free(ctx); + EVP_PKEY_assign_DSA(out, dsa); + return 1; + +err: + BN_CTX_free(ctx); + DSA_free(dsa); + return 0; +} + +static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) { + const DSA *dsa = key->pkey.dsa; + if (dsa == NULL || dsa->priv_key == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS); + return 0; + } + + /* See PKCS#11, v2.40, section 2.5. */ + CBB pkcs8, algorithm, oid, private_key; + if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) || + !DSA_marshal_parameters(&algorithm, dsa) || + !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || + !BN_marshal_asn1(&private_key, dsa->priv_key) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int int_dsa_size(const EVP_PKEY *pkey) { + return DSA_size(pkey->pkey.dsa); +} + +static int dsa_bits(const EVP_PKEY *pkey) { + return BN_num_bits(pkey->pkey.dsa->p); +} + +static int dsa_missing_parameters(const EVP_PKEY *pkey) { + DSA *dsa; + dsa = pkey->pkey.dsa; + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + return 1; + } + return 0; +} + +static int dup_bn_into(BIGNUM **out, BIGNUM *src) { + BIGNUM *a; + + a = BN_dup(src); + if (a == NULL) { + return 0; + } + BN_free(*out); + *out = a; + + return 1; +} + +static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { + if (!dup_bn_into(&to->pkey.dsa->p, from->pkey.dsa->p) || + !dup_bn_into(&to->pkey.dsa->q, from->pkey.dsa->q) || + !dup_bn_into(&to->pkey.dsa->g, from->pkey.dsa->g)) { + return 0; + } + + return 1; +} + +static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { + return BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) == 0 && + BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) == 0 && + BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g) == 0; +} + +static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { + return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0; +} + +static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); } + +const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = { + EVP_PKEY_DSA, + /* 1.2.840.10040.4.1 */ + {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7, + + dsa_pub_decode, + dsa_pub_encode, + dsa_pub_cmp, + + dsa_priv_decode, + dsa_priv_encode, + + NULL /* pkey_opaque */, + NULL /* pkey_supports_digest */, + + int_dsa_size, + dsa_bits, + + dsa_missing_parameters, + dsa_copy_parameters, + dsa_cmp_parameters, + + int_dsa_free, +}; diff --git a/external/boringssl/crypto/evp/p_ec.c b/external/boringssl/crypto/evp/p_ec.c new file mode 100644 index 0000000000..f92c87cf25 --- /dev/null +++ b/external/boringssl/crypto/evp/p_ec.c @@ -0,0 +1,236 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../ec/internal.h" + + +typedef struct { + /* 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; + + dctx->md = sctx->md; + + return 1; +} + +static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) { + EC_PKEY_CTX *dctx = ctx->data; + if (!dctx) { + return; + } + + 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) { + unsigned int sltmp; + 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, EVP_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!ECDSA_sign(0, 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) { + return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->pkey->pkey.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, 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; + + switch (type) { + 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, 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 */ + return 1; + + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } +} + +static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { + if (ctx->pkey == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET); + return 0; + } + EC_KEY *ec = EC_KEY_new(); + if (ec == NULL || + !EC_KEY_set_group(ec, EC_KEY_get0_group(ctx->pkey->pkey.ec)) || + !EC_KEY_generate_key(ec)) { + EC_KEY_free(ec); + return 0; + } + EVP_PKEY_assign_EC_KEY(pkey, ec); + return 1; +} + +const EVP_PKEY_METHOD ec_pkey_meth = { + EVP_PKEY_EC, + pkey_ec_init, + pkey_ec_copy, + pkey_ec_cleanup, + pkey_ec_keygen, + pkey_ec_sign, + pkey_ec_verify, + 0 /* verify_recover */, + 0 /* encrypt */, + 0 /* decrypt */, + pkey_ec_derive, + pkey_ec_ctrl, +}; diff --git a/external/boringssl/crypto/evp/p_ec_asn1.c b/external/boringssl/crypto/evp/p_ec_asn1.c new file mode 100644 index 0000000000..8d44dcdcee --- /dev/null +++ b/external/boringssl/crypto/evp/p_ec_asn1.c @@ -0,0 +1,257 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) { + const EC_KEY *ec_key = key->pkey.ec; + const EC_GROUP *group = EC_KEY_get0_group(ec_key); + const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key); + + /* See RFC 5480, section 2. */ + CBB spki, algorithm, oid, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) || + !EC_KEY_marshal_curve_name(&algorithm, group) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !EC_POINT_point2cbb(&key_bitstring, group, public_key, + POINT_CONVERSION_UNCOMPRESSED, NULL) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 5480, section 2. */ + + /* The parameters are a named curve. */ + EC_POINT *point = NULL; + EC_KEY *eckey = NULL; + EC_GROUP *group = EC_KEY_parse_curve_name(params); + if (group == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + eckey = EC_KEY_new(); + if (eckey == NULL || !EC_KEY_set_group(eckey, group)) { + goto err; + } + + point = EC_POINT_new(group); + if (point == NULL || + !EC_POINT_oct2point(group, point, CBS_data(key), CBS_len(key), NULL) || + !EC_KEY_set_public_key(eckey, point)) { + goto err; + } + + EC_GROUP_free(group); + EC_POINT_free(point); + EVP_PKEY_assign_EC_KEY(out, eckey); + return 1; + +err: + EC_GROUP_free(group); + EC_POINT_free(point); + 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 *out, CBS *params, CBS *key) { + /* See RFC 5915. */ + EC_GROUP *group = EC_KEY_parse_parameters(params); + if (group == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + EC_GROUP_free(group); + return 0; + } + + EC_KEY *ec_key = EC_KEY_parse_private_key(key, group); + EC_GROUP_free(group); + if (ec_key == NULL || CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + EC_KEY_free(ec_key); + return 0; + } + + EVP_PKEY_assign_EC_KEY(out, ec_key); + return 1; +} + +static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) { + const EC_KEY *ec_key = key->pkey.ec; + + /* Omit the redundant copy of the curve name. This contradicts RFC 5915 but + * aligns with PKCS #11. SEC 1 only says they may be omitted if known by other + * means. Both OpenSSL and NSS omit the redundant parameters, so we omit them + * as well. */ + unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS; + + /* See RFC 5915. */ + CBB pkcs8, algorithm, oid, private_key; + if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) || + !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) || + !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || + !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + 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) { + const EC_GROUP *group = EC_KEY_get0_group(pkey->pkey.ec); + if (group == NULL) { + ERR_clear_error(); + return 0; + } + return BN_num_bits(EC_GROUP_get0_order(group)); +} + +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); + if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) { + /* mismatch */ + return 0; + } + return 1; +} + +static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); } + +static int eckey_opaque(const EVP_PKEY *pkey) { + return EC_KEY_is_opaque(pkey->pkey.ec); +} + +const EVP_PKEY_ASN1_METHOD ec_asn1_meth = { + EVP_PKEY_EC, + /* 1.2.840.10045.2.1 */ + {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7, + + eckey_pub_decode, + eckey_pub_encode, + eckey_pub_cmp, + + eckey_priv_decode, + eckey_priv_encode, + + eckey_opaque, + 0 /* pkey_supports_digest */, + + int_ec_size, + ec_bits, + + ec_missing_parameters, + ec_copy_parameters, + ec_cmp_parameters, + + int_ec_free, +}; diff --git a/external/boringssl/crypto/evp/p_rsa.c b/external/boringssl/crypto/evp/p_rsa.c new file mode 100644 index 0000000000..a210657288 --- /dev/null +++ b/external/boringssl/crypto/evp/p_rsa.c @@ -0,0 +1,673 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../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) { + 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; + } + + BN_free(rctx->pub_exp); + OPENSSL_free(rctx->tbuf); + 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, 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, EVP_R_INVALID_DIGEST_LENGTH); + return 0; + } + + if (EVP_MD_type(rctx->md) == NID_mdc2) { + OPENSSL_PUT_ERROR(EVP, 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_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *sig, + size_t sig_len) { + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + const size_t key_len = EVP_PKEY_size(ctx->pkey); + + if (out == NULL) { + *out_len = key_len; + return 1; + } + + if (*out_len < key_len) { + OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!setup_tbuf(rctx, ctx)) { + return 0; + } + + if (rctx->md == NULL) { + const int ret = RSA_public_decrypt(sig_len, sig, rctx->tbuf, + ctx->pkey->pkey.rsa, rctx->pad_mode); + if (ret < 0) { + return 0; + } + *out_len = ret; + memcpy(out, rctx->tbuf, *out_len); + return 1; + } + + if (rctx->pad_mode != RSA_PKCS1_PADDING) { + return 0; + } + + uint8_t *asn1_prefix; + size_t asn1_prefix_len; + int asn1_prefix_allocated; + if (!RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len, + &asn1_prefix_allocated, EVP_MD_type(rctx->md), NULL, + 0)) { + return 0; + } + + size_t rslen; + int ok = 1; + if (!RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, sig_len, + RSA_PKCS1_PADDING) || + rslen < asn1_prefix_len || + CRYPTO_memcmp(rctx->tbuf, asn1_prefix, asn1_prefix_len) != 0) { + ok = 0; + } + + if (asn1_prefix_allocated) { + OPENSSL_free(asn1_prefix); + } + + if (!ok) { + return 0; + } + + const size_t result_len = rslen - asn1_prefix_len; + if (result_len != EVP_MD_size(rctx->md)) { + return 0; + } + + if (out != NULL) { + memcpy(out, rctx->tbuf + asn1_prefix_len, result_len); + } + *out_len = result_len; + + 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, 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, 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, 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, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); + return 0; + } + 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, EVP_R_INVALID_PSS_SALTLEN); + return 0; + } + if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) { + *(int *)p2 = rctx->saltlen; + } else { + if (p1 < -2) { + return 0; + } + rctx->saltlen = p1; + } + return 1; + + case EVP_PKEY_CTRL_RSA_KEYGEN_BITS: + if (p1 < 256) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_KEYBITS); + return 0; + } + rctx->nbits = p1; + return 1; + + case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: + if (!p2) { + return 0; + } + 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, EVP_R_INVALID_PADDING_MODE); + return 0; + } + 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, EVP_R_INVALID_MGF1_MD); + return 0; + } + 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, EVP_R_INVALID_PADDING_MODE); + return 0; + } + OPENSSL_free(rctx->oaep_label); + if (p2 && p1 > 0) { + rctx->oaep_label = p2; + rctx->oaep_labellen = p1; + } else { + rctx->oaep_label = NULL; + rctx->oaep_labellen = 0; + } + return 1; + + case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: + if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); + return 0; + } + CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen); + return 1; + + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } +} + +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, + pkey_rsa_init, + pkey_rsa_copy, + pkey_rsa_cleanup, + pkey_rsa_keygen, + pkey_rsa_sign, + pkey_rsa_verify, + pkey_rsa_verify_recover, + pkey_rsa_encrypt, + pkey_rsa_decrypt, + 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, uint8_t *label, + size_t label_len) { + if (label_len > INT_MAX) { + return 0; + } + + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_OAEP_LABEL, (int)label_len, + (void *)label); +} + +int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, + const uint8_t **out_label) { + CBS label; + if (!EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, &label)) { + return -1; + } + if (CBS_len(&label) > INT_MAX) { + OPENSSL_PUT_ERROR(EVP, ERR_R_OVERFLOW); + return -1; + } + *out_label = CBS_data(&label); + return (int)CBS_len(&label); +} diff --git a/external/boringssl/crypto/evp/p_rsa_asn1.c b/external/boringssl/crypto/evp/p_rsa_asn1.c new file mode 100644 index 0000000000..2c4b266d96 --- /dev/null +++ b/external/boringssl/crypto/evp/p_rsa_asn1.c @@ -0,0 +1,200 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../rsa/internal.h" +#include "internal.h" + + +static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) { + /* See RFC 3279, section 2.3.1. */ + CBB spki, algorithm, oid, null, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) || + !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !RSA_marshal_public_key(&key_bitstring, key->pkey.rsa) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 3279, section 2.3.1. */ + + /* The parameters must be NULL. */ + CBS null; + if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || + CBS_len(&null) != 0 || + CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + /* Estonian IDs issued between September 2014 to September 2015 are + * broken. See https://crbug.com/532048 and https://crbug.com/534766. + * + * TODO(davidben): Switch this to the strict version in March 2016 or when + * Chromium can force client certificates down a different codepath, whichever + * comes first. */ + RSA *rsa = RSA_parse_public_key_buggy(key); + if (rsa == NULL || CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + RSA_free(rsa); + return 0; + } + + EVP_PKEY_assign_RSA(out, 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(CBB *out, const EVP_PKEY *key) { + CBB pkcs8, algorithm, oid, null, private_key; + if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) || + !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) || + !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || + !RSA_marshal_private_key(&private_key, key->pkey.rsa) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* Per RFC 3447, A.1, the parameters have type NULL. */ + CBS null; + if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || + CBS_len(&null) != 0 || + CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + RSA *rsa = RSA_parse_private_key(key); + if (rsa == NULL || CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + RSA_free(rsa); + return 0; + } + + EVP_PKEY_assign_RSA(out, 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); } + +const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = { + EVP_PKEY_RSA, + /* 1.2.840.113549.1.1.1 */ + {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, 9, + + rsa_pub_decode, + rsa_pub_encode, + rsa_pub_cmp, + + rsa_priv_decode, + rsa_priv_encode, + + rsa_opaque, + rsa_supports_digest, + + int_rsa_size, + rsa_bits, + + 0,0,0, + + int_rsa_free, +}; diff --git a/external/boringssl/crypto/evp/pbkdf.c b/external/boringssl/crypto/evp/pbkdf.c new file mode 100644 index 0000000000..b06b922b0b --- /dev/null +++ b/external/boringssl/crypto/evp/pbkdf.c @@ -0,0 +1,151 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include + + +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); + + // RFC 2898 describes iterations (c) as being a "positive integer", so a + // value of 0 is an error. + // + // Unfortunatley not all consumers of PKCS5_PBKDF2_HMAC() check their return + // value, expecting it to succeed and unconditonally using |out_key|. + // As a precaution for such callsites in external code, the old behavior + // of iterations < 1 being treated as iterations == 1 is preserved, but + // additionally an error result is returned. + // + // TODO(eroman): Figure out how to remove this compatibility hack, or change + // the default to something more sensible like 2048. + if (iterations == 0) { + return 0; + } + + 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/external/boringssl/crypto/evp/pbkdf_test.cc b/external/boringssl/crypto/evp/pbkdf_test.cc new file mode 100644 index 0000000000..438ab644cb --- /dev/null +++ b/external/boringssl/crypto/evp/pbkdf_test.cc @@ -0,0 +1,220 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include +#include + + +// Prints out the data buffer as a sequence of hex bytes. +static void PrintDataHex(const void *data, size_t len) { + for (size_t i = 0; i < len; ++i) { + fprintf(stderr, "%02x", (int)((const uint8_t *)data)[i]); + } +} + +// Helper for testing that PBKDF2 derives the expected key from the given +// inputs. Returns 1 on success, 0 otherwise. +static bool TestPBKDF2(const void *password, size_t password_len, + const void *salt, size_t salt_len, unsigned iterations, + const EVP_MD *digest, size_t key_len, + const uint8_t *expected_key) { + uint8_t key[64]; + + if (key_len > sizeof(key)) { + fprintf(stderr, "Output buffer is not large enough.\n"); + return false; + } + + if (!PKCS5_PBKDF2_HMAC((const char *)password, password_len, + (const uint8_t *)salt, salt_len, iterations, digest, + key_len, key)) { + fprintf(stderr, "Call to PKCS5_PBKDF2_HMAC failed\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (memcmp(key, expected_key, key_len) != 0) { + fprintf(stderr, "Resulting key material does not match expectation\n"); + fprintf(stderr, "Expected:\n "); + PrintDataHex(expected_key, key_len); + fprintf(stderr, "\nActual:\n "); + PrintDataHex(key, key_len); + fprintf(stderr, "\n"); + return false; + } + + return true; +} + +// Tests deriving a key using an empty password (specified both as NULL and as +// non-NULL). Note that NULL has special meaning to HMAC initialization. +static bool TestEmptyPassword() { + const uint8_t kKey[] = {0xa3, 0x3d, 0xdd, 0xc3, 0x04, 0x78, 0x18, + 0x55, 0x15, 0x31, 0x1f, 0x87, 0x52, 0x89, + 0x5d, 0x36, 0xea, 0x43, 0x63, 0xa2}; + + if (!TestPBKDF2(NULL, 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey) || + !TestPBKDF2("", 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey)) { + return false; + } + + return true; +} + +// Tests deriving a key using an empty salt. Note that the expectation was +// generated using OpenSSL itself, and hence is not verified. +static bool TestEmptySalt() { + const uint8_t kKey[] = {0x8b, 0xc2, 0xf9, 0x16, 0x7a, 0x81, 0xcd, 0xcf, + 0xad, 0x12, 0x35, 0xcd, 0x90, 0x47, 0xf1, 0x13, + 0x62, 0x71, 0xc1, 0xf9, 0x78, 0xfc, 0xfc, 0xb3, + 0x5e, 0x22, 0xdb, 0xea, 0xfa, 0x46, 0x34, 0xf6}; + + if (!TestPBKDF2("password", 8, NULL, 0, 2, EVP_sha256(), sizeof(kKey), + kKey) || + !TestPBKDF2("password", 8, "", 0, 2, EVP_sha256(), sizeof(kKey), kKey)) { + return false; + } + + return true; +} + +// Exercises test vectors taken from https://tools.ietf.org/html/rfc6070. +// Note that each of these test vectors uses SHA-1 as the digest. +static bool TestRFC6070Vectors() { + const uint8_t kKey1[] = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, + 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, + 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6}; + const uint8_t kKey2[] = {0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, + 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, + 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57}; + const uint8_t kKey3[] = {0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3}; + + if (!TestPBKDF2("password", 8, "salt", 4, 1, EVP_sha1(), sizeof(kKey1), + kKey1) || + !TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha1(), sizeof(kKey2), + kKey2) || + !TestPBKDF2("pass\0word", 9, "sa\0lt", 5, 4096, EVP_sha1(), + sizeof(kKey3), kKey3)) { + return false; + } + + return true; +} + +// Tests key derivation using SHA-2 digests. +static bool TestSHA2() { + // This test was taken from: + // http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors. + const uint8_t kKey1[] = {0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, + 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, + 0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf, + 0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43}; + + // This test was taken from: + // http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors. + const uint8_t kKey2[] = { + 0x8c, 0x05, 0x11, 0xf4, 0xc6, 0xe5, 0x97, 0xc6, 0xac, 0x63, 0x15, + 0xd8, 0xf0, 0x36, 0x2e, 0x22, 0x5f, 0x3c, 0x50, 0x14, 0x95, 0xba, + 0x23, 0xb8, 0x68, 0xc0, 0x05, 0x17, 0x4d, 0xc4, 0xee, 0x71, 0x11, + 0x5b, 0x59, 0xf9, 0xe6, 0x0c, 0xd9, 0x53, 0x2f, 0xa3, 0x3e, 0x0f, + 0x75, 0xae, 0xfe, 0x30, 0x22, 0x5c, 0x58, 0x3a, 0x18, 0x6c, 0xd8, + 0x2b, 0xd4, 0xda, 0xea, 0x97, 0x24, 0xa3, 0xd3, 0xb8}; + + if (!TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha256(), sizeof(kKey1), + kKey1) || + !TestPBKDF2("passwordPASSWORDpassword", 24, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, + EVP_sha512(), sizeof(kKey2), kKey2)) { + return false; + } + + return true; +} + +// Tests key derivation using iterations=0. +// +// RFC 2898 defines the iteration count (c) as a "positive integer". So doing a +// key derivation with iterations=0 is ill-defined and should result in a +// failure. +static bool TestZeroIterations() { + static const char kPassword[] = "password"; + const size_t password_len = strlen(kPassword); + static const uint8_t kSalt[] = {1, 2, 3, 4}; + const size_t salt_len = sizeof(kSalt); + const EVP_MD *digest = EVP_sha1(); + + uint8_t key[10] = {0}; + const size_t key_len = sizeof(key); + + // Verify that calling with iterations=1 works. + if (!PKCS5_PBKDF2_HMAC(kPassword, password_len, kSalt, salt_len, + 1 /* iterations */, digest, key_len, key)) { + fprintf(stderr, "PBKDF2 failed with iterations=1\n"); + return false; + } + + // Flip the first key byte (so can later test if it got set). + const uint8_t expected_first_byte = key[0]; + key[0] = ~key[0]; + + // However calling it with iterations=0 fails. + if (PKCS5_PBKDF2_HMAC(kPassword, password_len, kSalt, salt_len, + 0 /* iterations */, digest, key_len, key)) { + fprintf(stderr, "PBKDF2 returned zero with iterations=0\n"); + return false; + } + + // For backwards compatibility, the iterations == 0 case still fills in + // the out key. + return key[0] == expected_first_byte; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestEmptyPassword()) { + fprintf(stderr, "TestEmptyPassword failed\n"); + return 1; + } + + if (!TestEmptySalt()) { + fprintf(stderr, "TestEmptySalt failed\n"); + return 1; + } + + if (!TestRFC6070Vectors()) { + fprintf(stderr, "TestRFC6070Vectors failed\n"); + return 1; + } + + if (!TestSHA2()) { + fprintf(stderr, "TestSHA2 failed\n"); + return 1; + } + + if (!TestZeroIterations()) { + fprintf(stderr, "TestZeroIterations failed\n"); + return 1; + } + + printf("PASS\n"); + ERR_free_strings(); + return 0; +} diff --git a/external/boringssl/crypto/evp/print.c b/external/boringssl/crypto/evp/print.c new file mode 100644 index 0000000000..56521ec56b --- /dev/null +++ b/external/boringssl/crypto/evp/print.c @@ -0,0 +1,527 @@ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../rsa/internal.h" + + +static int bn_print(BIO *bp, const char *number, const BIGNUM *num, + uint8_t *buf, int off) { + if (num == NULL) { + return 1; + } + + 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)) { + const char *neg = BN_is_negative(num) ? "-" : ""; + 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, + (BN_is_negative(num)) ? " (Negative)" : "") <= 0) { + return 0; + } + int n = BN_bn2bin(num, &buf[1]); + + if (buf[1] & 0x80) { + n++; + } else { + buf++; + } + + int i; + 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; +} + +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; + } +} + +/* RSA keys. */ + +static int do_rsa_print(BIO *out, const RSA *rsa, int off, + int include_private) { + const char *s, *str; + 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); + + if (rsa->additional_primes != NULL) { + size_t i; + + for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); + i++) { + const RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + update_buflen(ap->prime, &buf_len); + update_buflen(ap->exp, &buf_len); + update_buflen(ap->coeff, &buf_len); + } + } + } + + m = (uint8_t *)OPENSSL_malloc(buf_len + 10); + if (m == NULL) { + OPENSSL_PUT_ERROR(EVP, 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 (!bn_print(out, str, rsa->n, m, off) || + !bn_print(out, s, rsa->e, m, off)) { + goto err; + } + + if (include_private) { + if (!bn_print(out, "privateExponent:", rsa->d, m, off) || + !bn_print(out, "prime1:", rsa->p, m, off) || + !bn_print(out, "prime2:", rsa->q, m, off) || + !bn_print(out, "exponent1:", rsa->dmp1, m, off) || + !bn_print(out, "exponent2:", rsa->dmq1, m, off) || + !bn_print(out, "coefficient:", rsa->iqmp, m, off)) { + goto err; + } + + if (rsa->additional_primes != NULL && + sk_RSA_additional_prime_num(rsa->additional_primes) > 0) { + size_t i; + + if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) { + goto err; + } + for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); + i++) { + const RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + + if (BIO_printf(out, "otherPrimeInfo (prime %u):\n", + (unsigned)(i + 3)) <= 0 || + !bn_print(out, "prime:", ap->prime, m, off) || + !bn_print(out, "exponent:", ap->exp, m, off) || + !bn_print(out, "coeff:", ap->coeff, m, off)) { + goto err; + } + } + } + } + ret = 1; + +err: + 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); +} + + +/* DSA keys. */ + +static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) { + uint8_t *m = NULL; + int ret = 0; + size_t buf_len = 0; + const char *ktype = NULL; + + const BIGNUM *priv_key, *pub_key; + + priv_key = NULL; + if (ptype == 2) { + priv_key = x->priv_key; + } + + pub_key = NULL; + if (ptype > 0) { + pub_key = x->pub_key; + } + + ktype = "DSA-Parameters"; + if (ptype == 2) { + ktype = "Private-Key"; + } else if (ptype == 1) { + ktype = "Public-Key"; + } + + update_buflen(x->p, &buf_len); + update_buflen(x->q, &buf_len); + update_buflen(x->g, &buf_len); + update_buflen(priv_key, &buf_len); + update_buflen(pub_key, &buf_len); + + m = (uint8_t *)OPENSSL_malloc(buf_len + 10); + if (m == NULL) { + OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (priv_key) { + if (!BIO_indent(bp, off, 128) || + BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) { + goto err; + } + } + + if (!bn_print(bp, "priv:", priv_key, m, off) || + !bn_print(bp, "pub: ", pub_key, m, off) || + !bn_print(bp, "P: ", x->p, m, off) || + !bn_print(bp, "Q: ", x->q, m, off) || + !bn_print(bp, "G: ", x->g, m, off)) { + goto err; + } + ret = 1; + +err: + OPENSSL_free(m); + return ret; +} + +static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_dsa_print(bp, pkey->pkey.dsa, indent, 0); +} + +static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_dsa_print(bp, pkey->pkey.dsa, indent, 1); +} + +static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_dsa_print(bp, pkey->pkey.dsa, indent, 2); +} + + +/* EC keys. */ + +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; + } + order = BN_new(); + if (order == NULL || !EC_GROUP_get_order(group, order, NULL) || + BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) { + goto err; + } + + if ((priv_key != NULL) && + !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, reason); + } + OPENSSL_free(pub_key_bytes); + BN_free(order); + BN_CTX_free(ctx); + OPENSSL_free(buffer); + return ret; +} + +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); +} + + +typedef struct { + int type; + int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx); + int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); + int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); +} EVP_PKEY_PRINT_METHOD; + +static EVP_PKEY_PRINT_METHOD kPrintMethods[] = { + { + EVP_PKEY_RSA, + rsa_pub_print, + rsa_priv_print, + NULL /* param_print */, + }, + { + EVP_PKEY_DSA, + dsa_pub_print, + dsa_priv_print, + dsa_param_print, + }, + { + EVP_PKEY_EC, + eckey_pub_print, + eckey_priv_print, + eckey_param_print, + }, +}; + +static size_t kPrintMethodsLen = + sizeof(kPrintMethods) / sizeof(kPrintMethods[0]); + +static EVP_PKEY_PRINT_METHOD *find_method(int type) { + size_t i; + for (i = 0; i < kPrintMethodsLen; i++) { + if (kPrintMethods[i].type == type) { + return &kPrintMethods[i]; + } + } + return NULL; +} + +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 unsupported\n", kstr); + return 1; +} + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx) { + EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); + if (method != NULL && method->pub_print != NULL) { + return method->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) { + EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); + if (method != NULL && method->priv_print != NULL) { + return method->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) { + EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); + if (method != NULL && method->param_print != NULL) { + return method->param_print(out, pkey, indent, pctx); + } + return print_unsupported(out, pkey, indent, "Parameters"); +} diff --git a/external/boringssl/crypto/evp/sign.c b/external/boringssl/crypto/evp/sign.c new file mode 100644 index 0000000000..ced86bdf4b --- /dev/null +++ b/external/boringssl/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 + +#include +#include + +#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) || + !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) || + !EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len)) { + 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) || + !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest)) { + goto out; + } + ret = EVP_PKEY_verify(pkctx, sig, sig_len, m, m_len); + +out: + EVP_PKEY_CTX_free(pkctx); + return ret; +} + diff --git a/external/boringssl/crypto/ex_data.c b/external/boringssl/crypto/ex_data.c new file mode 100644 index 0000000000..d67abba2ba --- /dev/null +++ b/external/boringssl/crypto/ex_data.c @@ -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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +struct crypto_ex_data_func_st { + long argl; /* Arbitary long */ + void *argp; /* Arbitary void pointer */ + CRYPTO_EX_free *free_func; + CRYPTO_EX_dup *dup_func; +}; + +int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, int *out_index, + long argl, void *argp, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + CRYPTO_EX_DATA_FUNCS *funcs; + int ret = 0; + + funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS)); + if (funcs == NULL) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + return 0; + } + + funcs->argl = argl; + funcs->argp = argp; + funcs->dup_func = dup_func; + funcs->free_func = free_func; + + CRYPTO_STATIC_MUTEX_lock_write(&ex_data_class->lock); + + if (ex_data_class->meth == NULL) { + ex_data_class->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); + } + + if (ex_data_class->meth == NULL || + !sk_CRYPTO_EX_DATA_FUNCS_push(ex_data_class->meth, funcs)) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + OPENSSL_free(funcs); + goto err; + } + + *out_index = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth) - 1 + + ex_data_class->num_reserved; + ret = 1; + +err: + CRYPTO_STATIC_MUTEX_unlock_write(&ex_data_class->lock); + return ret; +} + +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, 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, 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); +} + +/* 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, + CRYPTO_EX_DATA_CLASS *ex_data_class) { + size_t n; + + *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_STATIC_MUTEX_lock_read(&ex_data_class->lock); + n = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth); + if (n > 0) { + *out = sk_CRYPTO_EX_DATA_FUNCS_dup(ex_data_class->meth); + } + CRYPTO_STATIC_MUTEX_unlock_read(&ex_data_class->lock); + + if (n > 0 && *out == NULL) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + +void CRYPTO_new_ex_data(CRYPTO_EX_DATA *ad) { + ad->sk = NULL; +} + +int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to, + const CRYPTO_EX_DATA *from) { + if (from->sk == NULL) { + /* In this case, |from| is blank, which is also the initial state of |to|, + * so there's nothing to do. */ + return 1; + } + + STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; + if (!get_func_pointers(&func_pointers, ex_data_class)) { + return 0; + } + + size_t i; + 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 + ex_data_class->num_reserved); + if (func_pointer->dup_func) { + func_pointer->dup_func(to, from, &ptr, i + ex_data_class->num_reserved, + func_pointer->argl, func_pointer->argp); + } + CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr); + } + + sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); + + return 1; +} + +void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, void *obj, + CRYPTO_EX_DATA *ad) { + if (ad->sk == NULL) { + /* Nothing to do. */ + return; + } + + STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; + if (!get_func_pointers(&func_pointers, ex_data_class)) { + /* TODO(davidben): This leaks memory on malloc error. */ + return; + } + + size_t i; + 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 + ex_data_class->num_reserved); + func_pointer->free_func(obj, ptr, ad, i + ex_data_class->num_reserved, + func_pointer->argl, func_pointer->argp); + } + } + + sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); + + sk_void_free(ad->sk); + ad->sk = NULL; +} + +void CRYPTO_cleanup_all_ex_data(void) {} diff --git a/external/boringssl/crypto/hkdf/CMakeLists.txt b/external/boringssl/crypto/hkdf/CMakeLists.txt new file mode 100644 index 0000000000..df9f0d0d69 --- /dev/null +++ b/external/boringssl/crypto/hkdf/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + hkdf + + OBJECT + + hkdf.c +) + +if(ENABLE_TESTS) +add_executable( + hkdf_test + + hkdf_test.c + + $ +) + +target_link_libraries(hkdf_test crypto) +add_dependencies(all_tests hkdf_test) +endif() diff --git a/external/boringssl/crypto/hkdf/hkdf.c b/external/boringssl/crypto/hkdf/hkdf.c new file mode 100644 index 0000000000..d80834d897 --- /dev/null +++ b/external/boringssl/crypto/hkdf/hkdf.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include + + +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 */ + uint8_t prk[EVP_MAX_MD_SIZE]; + size_t prk_len; + + if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt, + salt_len) || + !HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)) { + return 0; + } + + return 1; +} + +int HKDF_extract(uint8_t *out_key, size_t *out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, const uint8_t *salt, + size_t salt_len) { + /* https://tools.ietf.org/html/rfc5869#section-2.2 */ + + /* If salt is not given, HashLength zeros are used. However, HMAC does that + * internally already so we can ignore it.*/ + unsigned len; + if (HMAC(digest, salt, salt_len, secret, secret_len, out_key, &len) == NULL) { + OPENSSL_PUT_ERROR(HKDF, ERR_R_HMAC_LIB); + return 0; + } + *out_len = len; + assert(*out_len == EVP_MD_size(digest)); + return 1; +} + +int HKDF_expand(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + uint8_t *prk, size_t prk_len, const uint8_t *info, + size_t info_len) { + /* https://tools.ietf.org/html/rfc5869#section-2.3 */ + const size_t digest_len = EVP_MD_size(digest); + uint8_t previous[EVP_MAX_MD_SIZE]; + size_t n, done = 0; + unsigned i; + int ret = 0; + HMAC_CTX hmac; + + /* Expand key material to desired length. */ + n = (out_len + digest_len - 1) / digest_len; + if (out_len + digest_len < out_len || n > 255) { + OPENSSL_PUT_ERROR(HKDF, HKDF_R_OUTPUT_TOO_LARGE); + return 0; + } + + HMAC_CTX_init(&hmac); + if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL)) { + goto out; + } + + for (i = 0; i < n; i++) { + uint8_t ctr = i + 1; + size_t todo; + + if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) || + !HMAC_Update(&hmac, previous, digest_len))) { + goto out; + } + if (!HMAC_Update(&hmac, info, info_len) || + !HMAC_Update(&hmac, &ctr, 1) || + !HMAC_Final(&hmac, previous, NULL)) { + goto out; + } + + todo = digest_len; + if (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, ERR_R_HMAC_LIB); + } + return ret; +} diff --git a/external/boringssl/crypto/hkdf/hkdf_test.c b/external/boringssl/crypto/hkdf/hkdf_test.c new file mode 100644 index 0000000000..a0f75a96eb --- /dev/null +++ b/external/boringssl/crypto/hkdf/hkdf_test.c @@ -0,0 +1,296 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include +#include + +#include "../test/test_util.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 uint8_t prk[EVP_MAX_MD_SIZE]; + const size_t prk_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, + { + 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, + 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, + }, 32, + 42, { + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, + 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, + 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65 + } + }, + { + EVP_sha256, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f + }, 80, + { + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf + }, 80, + { + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, 80, + { + 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, + 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, + 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44, + }, 32, + 82, { + 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, + 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, + 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, + 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87 + } + }, + { + EVP_sha256, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, + 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04 + }, 32, + 42, { + 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, + 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, + 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8 + } + }, + { + EVP_sha1, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 11, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, + }, 13, + { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + }, 10, + { + 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb, + 0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43 + }, 20, + 42, { + 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, + 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, + 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96 + } + }, + { + EVP_sha1, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f + }, 80, + { + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf + }, 80, + { + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, 80, + { + 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b, + 0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6, + }, 20, + 82, { + 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, + 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, + 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, + 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4 + } + }, + { + EVP_sha1, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7, + 0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01, + }, 20, + 42, { + 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, + 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, + 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18 + } + }, + { + EVP_sha1, + { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e, + 0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd, + }, 20, + 42, { + 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a, + 0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d, + 0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48 + } + }, +}; + +int main(void) { + uint8_t buf[82], prk[EVP_MAX_MD_SIZE]; + size_t i, prk_len; + + CRYPTO_library_init(); + + for (i = 0; i < sizeof(kTests) / sizeof(kTests[0]); i++) { + const hkdf_test_vector_t *test = &kTests[i]; + if (!HKDF_extract(prk, &prk_len, test->md_func(), test->ikm, test->ikm_len, + test->salt, test->salt_len)) { + fprintf(stderr, "Call to HKDF_extract failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (prk_len != test->prk_len || + memcmp(prk, test->prk, test->prk_len) != 0) { + fprintf(stderr, "%zu: Resulting PRK does not match test vector\n", i); + return 1; + } + if (!HKDF_expand(buf, test->out_len, test->md_func(), prk, prk_len, + test->info, test->info_len)) { + fprintf(stderr, "Call to HKDF_expand failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (memcmp(buf, test->out, test->out_len) != 0) { + fprintf(stderr, + "%zu: Resulting key material does not match test vector\n", i); + return 1; + } + + if (!HKDF(buf, test->out_len, test->md_func(), test->ikm, test->ikm_len, + test->salt, test->salt_len, test->info, test->info_len)) { + fprintf(stderr, "Call to HKDF failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (memcmp(buf, test->out, test->out_len) != 0) { + fprintf(stderr, + "%zu: Resulting key material does not match test vector\n", i); + return 1; + } + } + + printf("PASS\n"); + ERR_free_strings(); + return 0; +} diff --git a/external/boringssl/crypto/hmac/CMakeLists.txt b/external/boringssl/crypto/hmac/CMakeLists.txt new file mode 100644 index 0000000000..40b73bcd51 --- /dev/null +++ b/external/boringssl/crypto/hmac/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + hmac + + OBJECT + + hmac.c +) + + +if(ENABLE_TESTS) +add_executable( + hmac_test + + hmac_test.cc + + $ +) + +target_link_libraries(hmac_test crypto) +add_dependencies(all_tests hmac_test) +endif() diff --git a/external/boringssl/crypto/hmac/hmac.c b/external/boringssl/crypto/hmac/hmac.c new file mode 100644 index 0000000000..bccc5c02bd --- /dev/null +++ b/external/boringssl/crypto/hmac/hmac.c @@ -0,0 +1,214 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include + + +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_ex(&ctx, key, key_len, evp_md, NULL) || + !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; + 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(HMAC_CTX)); +} + +int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_MD *md, ENGINE *impl) { + if (md == NULL) { + md = ctx->md; + } + + /* If either |key| is non-NULL or |md| has changed, initialize with a new key + * rather than rewinding the previous one. + * + * TODO(davidben,eroman): Passing the previous |md| with a NULL |key| is + * ambiguous between using the empty key and reusing the previous key. There + * exist callers which intend the latter, but the former is an awkward edge + * case. Fix to API to avoid this. */ + if (md != ctx->md || key != NULL) { + size_t i; + uint8_t pad[EVP_MAX_MD_BLOCK_SIZE]; + uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE]; + unsigned key_block_len; + + size_t block_size = EVP_MD_block_size(md); + assert(block_size <= sizeof(key_block)); + if (block_size < key_len) { + /* Long keys are hashed. */ + if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl) || + !EVP_DigestUpdate(&ctx->md_ctx, key, key_len) || + !EVP_DigestFinal_ex(&ctx->md_ctx, key_block, &key_block_len)) { + return 0; + } + } else { + assert(key_len <= sizeof(key_block)); + memcpy(key_block, key, key_len); + key_block_len = (unsigned)key_len; + } + /* Keys are then padded with zeros. */ + if (key_block_len != EVP_MAX_MD_BLOCK_SIZE) { + memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len); + } + + for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) { + pad[i] = 0x36 ^ key_block[i]; + } + if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) || + !EVP_DigestUpdate(&ctx->i_ctx, pad, EVP_MD_block_size(md))) { + return 0; + } + + for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) { + pad[i] = 0x5c ^ key_block[i]; + } + if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) || + !EVP_DigestUpdate(&ctx->o_ctx, pad, EVP_MD_block_size(md))) { + return 0; + } + + ctx->md = md; + } + + if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx)) { + return 0; + } + + return 1; +} + +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]; + + /* TODO(davidben): The only thing that can officially fail here is + * |EVP_MD_CTX_copy_ex|, but even that should be impossible in this case. */ + 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; + } + + dest->md = src->md; + return 1; +} + +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/external/boringssl/crypto/hmac/hmac_test.cc b/external/boringssl/crypto/hmac/hmac_test.cc new file mode 100644 index 0000000000..da390ef814 --- /dev/null +++ b/external/boringssl/crypto/hmac/hmac_test.cc @@ -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.] */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +static const EVP_MD *GetDigest(const std::string &name) { + if (name == "MD5") { + return EVP_md5(); + } else if (name == "SHA1") { + return EVP_sha1(); + } else if (name == "SHA224") { + return EVP_sha224(); + } else if (name == "SHA256") { + return EVP_sha256(); + } else if (name == "SHA384") { + return EVP_sha384(); + } else if (name == "SHA512") { + return EVP_sha512(); + } + return nullptr; +} + +static bool TestHMAC(FileTest *t, void *arg) { + std::string digest_str; + if (!t->GetAttribute(&digest_str, "HMAC")) { + return false; + } + const EVP_MD *digest = GetDigest(digest_str); + if (digest == nullptr) { + t->PrintLine("Unknown digest '%s'", digest_str.c_str()); + return false; + } + + std::vector key, input, output; + if (!t->GetBytes(&key, "Key") || + !t->GetBytes(&input, "Input") || + !t->GetBytes(&output, "Output")) { + return false; + } + + // Test using the one-shot API. + uint8_t mac[EVP_MAX_MD_SIZE]; + unsigned mac_len; + if (nullptr == HMAC(digest, key.data(), key.size(), input.data(), + input.size(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("One-shot API failed."); + return false; + } + + // Test using HMAC_CTX. + ScopedHMAC_CTX ctx; + if (!HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr) || + !HMAC_Update(ctx.get(), input.data(), input.size()) || + !HMAC_Final(ctx.get(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("HMAC_CTX failed."); + return false; + } + + // Test that an HMAC_CTX may be reset with the same key. + if (!HMAC_Init_ex(ctx.get(), nullptr, 0, digest, nullptr) || + !HMAC_Update(ctx.get(), input.data(), input.size()) || + !HMAC_Final(ctx.get(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("HMAC_CTX with reset failed."); + return false; + } + + // Test feeding the input in byte by byte. + if (!HMAC_Init_ex(ctx.get(), nullptr, 0, nullptr, nullptr)) { + t->PrintLine("HMAC_CTX streaming failed."); + return false; + } + for (size_t i = 0; i < input.size(); i++) { + if (!HMAC_Update(ctx.get(), &input[i], 1)) { + t->PrintLine("HMAC_CTX streaming failed."); + return false; + } + } + if (!HMAC_Final(ctx.get(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("HMAC_CTX streaming failed."); + return false; + } + + return true; +} + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestHMAC, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/hmac/hmac_tests.txt b/external/boringssl/crypto/hmac/hmac_tests.txt new file mode 100644 index 0000000000..53f3f8f9a9 --- /dev/null +++ b/external/boringssl/crypto/hmac/hmac_tests.txt @@ -0,0 +1,120 @@ +HMAC = MD5 +# Note: The empty key results in passing NULL to HMAC_Init_ex, so this tests +# that HMAC_CTX and HMAC treat NULL as the empty key initially. +Key = +Input = "More text test vectors to stuff up EBCDIC machines :-)" +Output = e9139d1e6ee064ef8cf514fc7dc83e86 + +# HMAC tests from RFC2104 +HMAC = MD5 +Key = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Input = "Hi There" +Output = 9294727a3638bb1c13f48ef8158bfc9d + +HMAC = MD5 +Key = "Jefe" +Input = "what do ya want for nothing?" +Output = 750c783e6ab0b503eaa86e310a5db738 + +HMAC = MD5 +Key = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Input = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Output = 56be34521d144c88dbb8c733f0e8b3f6 + +# HMAC tests from NIST test data + +HMAC = SHA1 +Input = "Sample message for keylen=blocklen" +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F +Output = 5FD596EE78D5553C8FF4E72D266DFD192366DA29 + +HMAC = SHA1 +Input = "Sample message for keylen +#include + +#if defined(_MSC_VER) +#if !defined(__cplusplus) || _MSC_VER < 1900 +#define alignas(x) __declspec(align(x)) +#define alignof __alignof +#endif +#else +#include +#endif + +#if defined(OPENSSL_NO_THREADS) +#elif defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#else +#include +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + +#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 + + +#if !defined(_MSC_VER) && defined(OPENSSL_64_BIT) +typedef __int128_t int128_t; +typedef __uint128_t uint128_t; +#endif + + +/* buffers_alias returns one if |a| and |b| alias and zero otherwise. */ +static inline int buffers_alias(const uint8_t *a, size_t a_len, + const uint8_t *b, size_t b_len) { + /* Cast |a| and |b| to integers. In C, pointer comparisons between unrelated + * objects are undefined whereas pointer to integer conversions are merely + * implementation-defined. We assume the implementation defined it in a sane + * way. */ + uintptr_t a_u = (uintptr_t)a; + uintptr_t b_u = (uintptr_t)b; + return a_u + a_len > b_u && b_u + b_len > a_u; +} + + +/* 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))); +} + + +/* Thread-safe initialisation. */ + +/* Android's mingw-w64 has some prototypes for INIT_ONCE, but is missing + * others. Work around the missing ones. + * + * TODO(davidben): Remove this once Android's mingw-w64 is upgraded. See + * b/26523949. */ +#if defined(__MINGW32__) && !defined(INIT_ONCE_STATIC_INIT) +typedef RTL_RUN_ONCE INIT_ONCE; +#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT +#endif + +#if defined(OPENSSL_NO_THREADS) +typedef uint32_t CRYPTO_once_t; +#define CRYPTO_ONCE_INIT 0 +#elif defined(OPENSSL_WINDOWS) +typedef INIT_ONCE CRYPTO_once_t; +#define CRYPTO_ONCE_INIT INIT_ONCE_STATIC_INIT +#else +typedef pthread_once_t CRYPTO_once_t; +#define CRYPTO_ONCE_INIT PTHREAD_ONCE_INIT +#endif + +/* CRYPTO_once calls |init| exactly once per process. This is thread-safe: if + * concurrent threads call |CRYPTO_once| with the same |CRYPTO_once_t| argument + * then they will block until |init| completes, but |init| will have only been + * called once. + * + * The |once| argument must be a |CRYPTO_once_t| that has been initialised with + * the value |CRYPTO_ONCE_INIT|. */ +OPENSSL_EXPORT void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)); + + +/* Reference counting. */ + +/* CRYPTO_REFCOUNT_MAX is the value at which the reference count saturates. */ +#define CRYPTO_REFCOUNT_MAX 0xffffffff + +/* CRYPTO_refcount_inc atomically increments the value at |*count| unless the + * value would overflow. It's safe for multiple threads to concurrently call + * this or |CRYPTO_refcount_dec_and_test_zero| on the same + * |CRYPTO_refcount_t|. */ +OPENSSL_EXPORT void CRYPTO_refcount_inc(CRYPTO_refcount_t *count); + +/* CRYPTO_refcount_dec_and_test_zero tests the value at |*count|: + * if it's zero, it crashes the address space. + * if it's the maximum value, it returns zero. + * otherwise, it atomically decrements it and returns one iff the resulting + * value is zero. + * + * It's safe for multiple threads to concurrently call this or + * |CRYPTO_refcount_inc| on the same |CRYPTO_refcount_t|. */ +OPENSSL_EXPORT int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count); + + +/* Locks. + * + * Two types of locks are defined: |CRYPTO_MUTEX|, which can be used in + * structures as normal, and |struct CRYPTO_STATIC_MUTEX|, which can be used as + * a global lock. A global lock must be initialised to the value + * |CRYPTO_STATIC_MUTEX_INIT|. + * + * |CRYPTO_MUTEX| can appear in public structures and so is defined in + * thread.h as a structure large enough to fit the real type. The global lock is + * a different type so it may be initialized with platform initializer macros.*/ + +#if defined(OPENSSL_NO_THREADS) +struct CRYPTO_STATIC_MUTEX { + char padding; /* Empty structs have different sizes in C and C++. */ +}; +#define CRYPTO_STATIC_MUTEX_INIT { 0 } +#elif defined(OPENSSL_WINDOWS) +struct CRYPTO_STATIC_MUTEX { + SRWLOCK lock; +}; +#define CRYPTO_STATIC_MUTEX_INIT { SRWLOCK_INIT } +#else +struct CRYPTO_STATIC_MUTEX { + pthread_rwlock_t lock; +}; +#define CRYPTO_STATIC_MUTEX_INIT { PTHREAD_RWLOCK_INITIALIZER } +#endif + +/* CRYPTO_MUTEX_init initialises |lock|. If |lock| is a static variable, use a + * |CRYPTO_STATIC_MUTEX|. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_lock_read locks |lock| such that other threads may also have a + * read lock, but none may have a write lock. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_lock_write locks |lock| such that no other thread has any type + * of lock on it. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_unlock_read unlocks |lock| for reading. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_unlock_write unlocks |lock| for writing. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_cleanup releases all resources held by |lock|. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_lock_read locks |lock| such that other threads may also + * have a read lock, but none may have a write lock. The |lock| variable does + * not need to be initialised by any function, but must have been statically + * initialised with |CRYPTO_STATIC_MUTEX_INIT|. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_read( + struct CRYPTO_STATIC_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_lock_write locks |lock| such that no other thread has + * any type of lock on it. The |lock| variable does not need to be initialised + * by any function, but must have been statically initialised with + * |CRYPTO_STATIC_MUTEX_INIT|. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_write( + struct CRYPTO_STATIC_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_unlock_read unlocks |lock| for reading. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_read( + struct CRYPTO_STATIC_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_unlock_write unlocks |lock| for writing. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_write( + struct CRYPTO_STATIC_MUTEX *lock); + + +/* Thread local storage. */ + +/* thread_local_data_t enumerates the types of thread-local data that can be + * stored. */ +typedef enum { + OPENSSL_THREAD_LOCAL_ERR = 0, + OPENSSL_THREAD_LOCAL_RAND, + OPENSSL_THREAD_LOCAL_URANDOM_BUF, + OPENSSL_THREAD_LOCAL_TEST, + NUM_OPENSSL_THREAD_LOCALS, +} thread_local_data_t; + +/* thread_local_destructor_t is the type of a destructor function that will be + * called when a thread exits and its thread-local storage needs to be freed. */ +typedef void (*thread_local_destructor_t)(void *); + +/* CRYPTO_get_thread_local gets the pointer value that is stored for the + * current thread for the given index, or NULL if none has been set. */ +OPENSSL_EXPORT void *CRYPTO_get_thread_local(thread_local_data_t value); + +/* CRYPTO_set_thread_local sets a pointer value for the current thread at the + * given index. This function should only be called once per thread for a given + * |index|: rather than update the pointer value itself, update the data that + * is pointed to. + * + * The destructor function will be called when a thread exits to free this + * thread-local data. All calls to |CRYPTO_set_thread_local| with the same + * |index| should have the same |destructor| argument. The destructor may be + * called with a NULL argument if a thread that never set a thread-local + * pointer for |index|, exits. The destructor may be called concurrently with + * different arguments. + * + * This function returns one on success or zero on error. If it returns zero + * then |destructor| has been called with |value| already. */ +OPENSSL_EXPORT int CRYPTO_set_thread_local( + thread_local_data_t index, void *value, + thread_local_destructor_t destructor); + + +/* ex_data */ + +typedef struct crypto_ex_data_func_st CRYPTO_EX_DATA_FUNCS; + +/* CRYPTO_EX_DATA_CLASS tracks the ex_indices registered for a type which + * supports ex_data. It should defined as a static global within the module + * which defines that type. */ +typedef struct { + struct CRYPTO_STATIC_MUTEX lock; + STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; + /* num_reserved is one if the ex_data index zero is reserved for legacy + * |TYPE_get_app_data| functions. */ + uint8_t num_reserved; +} CRYPTO_EX_DATA_CLASS; + +#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_STATIC_MUTEX_INIT, NULL, 0} +#define CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA \ + {CRYPTO_STATIC_MUTEX_INIT, NULL, 1} + +/* CRYPTO_get_ex_new_index allocates a new index for |ex_data_class| and writes + * it to |*out_index|. Each class of object should provide a wrapper function + * that uses the correct |CRYPTO_EX_DATA_CLASS|. It returns one on success and + * zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, + int *out_index, long argl, + void *argp, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); + +/* CRYPTO_set_ex_data sets an extra data pointer on a given object. Each class + * of object should provide a wrapper function. */ +OPENSSL_EXPORT int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val); + +/* CRYPTO_get_ex_data returns an extra data pointer for a given object, or NULL + * if no such index exists. Each class of object should provide a wrapper + * function. */ +OPENSSL_EXPORT void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int index); + +/* CRYPTO_new_ex_data initialises a newly allocated |CRYPTO_EX_DATA|. */ +OPENSSL_EXPORT void CRYPTO_new_ex_data(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(CRYPTO_EX_DATA_CLASS *ex_data_class, + 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(CRYPTO_EX_DATA_CLASS *ex_data_class, + void *obj, CRYPTO_EX_DATA *ad); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_INTERNAL_H */ diff --git a/external/boringssl/crypto/lhash/CMakeLists.txt b/external/boringssl/crypto/lhash/CMakeLists.txt new file mode 100644 index 0000000000..f7a00dee8a --- /dev/null +++ b/external/boringssl/crypto/lhash/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + lhash + + OBJECT + + lhash.c +) + +if(ENABLE_TESTS) +add_executable( + lhash_test + + lhash_test.c + + $ +) + +target_link_libraries(lhash_test crypto) +add_dependencies(all_tests lhash_test) +endif() diff --git a/external/boringssl/crypto/lhash/lhash.c b/external/boringssl/crypto/lhash/lhash.c new file mode 100644 index 0000000000..257900eab5 --- /dev/null +++ b/external/boringssl/crypto/lhash/lhash.c @@ -0,0 +1,346 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include + +/* 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/external/boringssl/crypto/lhash/lhash_test.c b/external/boringssl/crypto/lhash/lhash_test.c new file mode 100644 index 0000000000..309b765d31 --- /dev/null +++ b/external/boringssl/crypto/lhash/lhash_test.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. */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L +#endif + +#include +#include + +#include +#include +#include + +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); + if (lh == NULL) { + return 1; + } + + 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); +#if defined(OPENSSL_WINDOWS) + dummy_lh_insert(&dummy_lh, &s2, _strdup(s)); +#else + dummy_lh_insert(&dummy_lh, &s2, strdup(s)); +#endif + + 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/external/boringssl/crypto/lhash/make_macros.sh b/external/boringssl/crypto/lhash/make_macros.sh new file mode 100644 index 0000000000..8a876af33f --- /dev/null +++ b/external/boringssl/crypto/lhash/make_macros.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +include_dir=../../include/openssl +out=${include_dir}/lhash_macros.h + +cat > $out << 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 >> $out << 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 ${include_dir}/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 $out diff --git a/external/boringssl/crypto/md4/CMakeLists.txt b/external/boringssl/crypto/md4/CMakeLists.txt new file mode 100644 index 0000000000..59140a72de --- /dev/null +++ b/external/boringssl/crypto/md4/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + md4 + + OBJECT + + md4.c +) diff --git a/external/boringssl/crypto/md4/md4.c b/external/boringssl/crypto/md4/md4.c new file mode 100644 index 0000000000..f79da9fd03 --- /dev/null +++ b/external/boringssl/crypto/md4/md4.c @@ -0,0 +1,234 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + + +uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out) { + MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, data, len); + MD4_Final(out, &ctx); + + return out; +} + +/* Implemented from RFC1186 The MD4 Message-Digest Algorithm. */ + +int MD4_Init(MD4_CTX *md4) { + memset(md4, 0, sizeof(MD4_CTX)); + md4->h[0] = 0x67452301UL; + md4->h[1] = 0xefcdab89UL; + md4->h[2] = 0x98badcfeUL; + md4->h[3] = 0x10325476UL; + return 1; +} + +void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#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 { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + 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 , 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 ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) + +#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(uint32_t *state, const uint8_t *data, size_t num) { + 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 = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + + 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 = state[0] += A; + B = state[1] += B; + C = state[2] += C; + D = state[3] += D; + } +} diff --git a/external/boringssl/crypto/md5/CMakeLists.txt b/external/boringssl/crypto/md5/CMakeLists.txt new file mode 100644 index 0000000000..a37c47e459 --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/md5/asm/md5-586.pl b/external/boringssl/crypto/md5/asm/md5-586.pl new file mode 100644 index 0000000000..6cb66bb499 --- /dev/null +++ b/external/boringssl/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"); + + # ¬($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/external/boringssl/crypto/md5/asm/md5-x86_64.pl b/external/boringssl/crypto/md5/asm/md5-x86_64.pl new file mode 100644 index 0000000000..77a6e01dd8 --- /dev/null +++ b/external/boringssl/crypto/md5/asm/md5-x86_64.pl @@ -0,0 +1,370 @@ +#!/usr/bin/perl -w +# +# MD5 optimized for AMD64. +# +# Author: Marc Bevand +# 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 .= <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 .= <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/external/boringssl/crypto/md5/md5.c b/external/boringssl/crypto/md5/md5.c new file mode 100644 index 0000000000..66483b847f --- /dev/null +++ b/external/boringssl/crypto/md5/md5.c @@ -0,0 +1,275 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +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->h[0] = 0x67452301UL; + md5->h[1] = 0xefcdab89UL; + md5->h[2] = 0x98badcfeUL; + md5->h[3] = 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(uint32_t *state, const uint8_t *data, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#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 { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + 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 , 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 ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) + +#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(uint32_t *state, const uint8_t *data, size_t num) { + 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 = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + + 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 = state[0] += A; + B = state[1] += B; + C = state[2] += C; + D = state[3] += D; + } +} +#endif diff --git a/external/boringssl/crypto/mem.c b/external/boringssl/crypto/mem.c new file mode 100644 index 0000000000..527edd9348 --- /dev/null +++ b/external/boringssl/crypto/mem.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.] */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L /* needed for strdup, snprintf, vprintf etc */ +#endif + +#include + +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include + +/* Work around a clang-cl bug: SecureZeroMemory() below uses __stosb() but + * windows.h only declares that intrinsic and then uses `#pragma intrinsic` for + * it. clang-cl doesn't implement `#pragma intrinsic` yet; it instead defines + * the function as an always-inline symbol in its intrin.h. + * TODO(thakis): Remove this once http://llvm.org/PR19898 is fixed. + */ +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#else +#include +#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) { + const uint8_t *a = in_a; + const uint8_t *b = in_b; + uint8_t x = 0; + + for (size_t 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; +} + +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) + +char *OPENSSL_strdup(const char *s) { return _strdup(s); } + +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 + +char *OPENSSL_strdup(const char *s) { return strdup(s); } + +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/external/boringssl/crypto/modes/CMakeLists.txt b/external/boringssl/crypto/modes/CMakeLists.txt new file mode 100644 index 0000000000..6dae9f6a87 --- /dev/null +++ b/external/boringssl/crypto/modes/CMakeLists.txt @@ -0,0 +1,68 @@ +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) + +if(ENABLE_TESTS) +add_executable( + gcm_test + + gcm_test.c + + $ +) + +target_link_libraries(gcm_test crypto) +add_dependencies(all_tests gcm_test) +endif() diff --git a/external/boringssl/crypto/modes/asm/aesni-gcm-x86_64.pl b/external/boringssl/crypto/modes/asm/aesni-gcm-x86_64.pl new file mode 100644 index 0000000000..5d58bbbbc9 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/aesni-gcm-x86_64.pl @@ -0,0 +1,1087 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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"; + +# This must be kept in sync with |$avx| in ghash-x86_64.pl; otherwise tags will +# be computed incorrectly. +# +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +$avx = 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 + + # At this point, the current block of 96 (0x60) bytes has already been + # loaded into registers. Concurrently with processing it, we want to + # load the next 96 bytes of input for the next round. Obviously, we can + # only do this if there are at least 96 more bytes of input beyond the + # input we're currently processing, or else we'd read past the end of + # the input buffer. Here, we set |%r12| to 96 if there are at least 96 + # bytes of input beyond the 96 bytes we're already processing, and we + # set |%r12| to 0 otherwise. In the case where we set |%r12| to 96, + # we'll read in the next block so that it is in registers for the next + # loop iteration. In the case where we set |%r12| to 0, we'll re-read + # the current block and then ignore what we re-read. + # + # At this point, |$in0| points to the current (already read into + # registers) block, and |$end0| points to 2*96 bytes before the end of + # the input. Thus, |$in0| > |$end0| means that we do not have the next + # 96-byte block to read in, and |$in0| <= |$end0| means we do. + 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 + + # We call |_aesni_ctr32_ghash_6x|, which requires at least 96 (0x60) + # bytes of input. + 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 + + # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0) + # bytes before the end of the input. Note, in particular, that this is + # correct even if |$len| is not an even multiple of 96 or 16. XXX: This + # seems to require that |$inp| + |$len| >= 2*96 (0xc0); i.e. |$inp| must + # not be near the very beginning of the address space when |$len| < 2*96 + # (0xc0). + 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 -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_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 + + # We call |_aesni_ctr32_6x| twice, each call consuming 96 bytes of + # input. Then we call |_aesni_ctr32_ghash_6x|, which requires at + # least 96 more bytes of input. + 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 + + # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0) + # bytes before the end of the input. Note, in particular, that this is + # correct even if |$len| is not an even multiple of 96 or 16. Unlike in + # the decryption case, there's no caveat that |$out| must not be near + # the very beginning of the address space, because we know that + # |$len| >= 3*96 from the check above, and so we know + # |$out| + |$len| >= 2*96 (0xc0). + 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 " +.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->RipRsp + + 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/external/boringssl/crypto/modes/asm/ghash-armv4.pl b/external/boringssl/crypto/modes/asm/ghash-armv4.pl new file mode 100644 index 0000000000..bb0dba5f53 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghash-armv4.pl @@ -0,0 +1,512 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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, A15 - in 7.63, +# 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... + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + 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=<<___; +#include + +.syntax unified + +.text +.code 32 + +#ifdef __clang__ +#define ldrplb ldrbpl +#define ldrneb ldrbne +#endif + +.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 +.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 +.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_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.global gcm_init_neon +.type gcm_init_neon,%function +.align 4 +gcm_init_neon: + vld1.64 $IN#hi,[r1]! @ load H + vmov.i8 $t0,#0xe1 + vld1.64 $IN#lo,[r1] + 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} + + ret @ bx lr +.size gcm_init_neon,.-gcm_init_neon + +.global gcm_gmult_neon +.type gcm_gmult_neon,%function +.align 4 +gcm_gmult_neon: + vld1.64 $IN#hi,[$Xi]! @ load Xi + vld1.64 $IN#lo,[$Xi]! + 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 +.type gcm_ghash_neon,%function +.align 4 +gcm_ghash_neon: + vld1.64 $Xl#hi,[$Xi]! @ load Xi + vld1.64 $Xl#lo,[$Xi]! + 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]! @ write out Xi + vst1.64 $Xl#lo,[$Xi] + + ret @ bx lr +.size gcm_ghash_neon,.-gcm_ghash_neon +#endif +___ +} +$code.=<<___; +.asciz "GHASH for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +___ + +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/\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/external/boringssl/crypto/modes/asm/ghash-x86.pl b/external/boringssl/crypto/modes/asm/ghash-x86.pl new file mode 100644 index 0000000000..0269169fa7 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghash-x86.pl @@ -0,0 +1,1393 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 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=0; +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 "); +&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/external/boringssl/crypto/modes/asm/ghash-x86_64.pl b/external/boringssl/crypto/modes/asm/ghash-x86_64.pl new file mode 100644 index 0000000000..5a11fb94c6 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghash-x86_64.pl @@ -0,0 +1,1742 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 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"; + +# This must be kept in sync with |$avx| in aesni-gcm-x86_64.pl; otherwise tags +# will be computed incorrectly. +# +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +$avx = 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 " +.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->RipRsp + + 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/external/boringssl/crypto/modes/asm/ghashv8-armx.pl b/external/boringssl/crypto/modes/asm/ghashv8-armx.pl new file mode 100644 index 0000000000..3a7b8d8b01 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghashv8-armx.pl @@ -0,0 +1,422 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 from bits-n-pieces from +# other assembly modules. Just like aesv8-armx.pl this module +# supports both AArch32 and AArch64 execution modes. +# +# July 2014 +# +# Implement 2x aggregated reduction [see ghash-x86.pl for background +# information]. +# +# Current performance in cycles per processed byte: +# +# PMULL[2] 32-bit NEON(*) +# Apple A7 0.92 5.62 +# Cortex-A53 1.01 8.39 +# Cortex-A57 1.17 7.61 +# Denver 0.71 6.02 +# +# (*) presented for reference/comparison purposes; + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$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,$xC2,$H,$Hhl,$H2)=map("q$_",(8..14)); + +$code=<<___; +#include + +.text +___ +$code.=<<___ if ($flavour =~ /64/); +#if !defined(__clang__) +.arch armv8-a+crypto +#endif +___ +$code.=".fpu neon\n.code 32\n" if ($flavour !~ /64/); + +################################################################################ +# void gcm_init_v8(u128 Htable[16],const u64 H[2]); +# +# input: 128-bit H - secret parameter E(K,0^128) +# output: precomputed table filled with degrees of twisted H; +# H is twisted to handle reverse bitness of GHASH; +# only few of 16 slots of Htable[16] are used; +# data is opaque to outside world (which allows to +# optimize the code independently); +# +$code.=<<___; +.global gcm_init_v8 +.type gcm_init_v8,%function +.align 4 +gcm_init_v8: + vld1.64 {$t1},[x1] @ load input H + vmov.i8 $xC2,#0xe1 + vshl.i64 $xC2,$xC2,#57 @ 0xc2.0 + vext.8 $IN,$t1,$t1,#8 + vshr.u64 $t2,$xC2,#63 + vdup.32 $t1,${t1}[1] + vext.8 $t0,$t2,$xC2,#8 @ t0=0xc2....01 + vshr.u64 $t2,$IN,#63 + vshr.s32 $t1,$t1,#31 @ broadcast carry bit + vand $t2,$t2,$t0 + vshl.i64 $IN,$IN,#1 + vext.8 $t2,$t2,$t2,#8 + vand $t0,$t0,$t1 + vorr $IN,$IN,$t2 @ H<<<=1 + veor $H,$IN,$t0 @ twisted H + vst1.64 {$H},[x0],#16 @ store Htable[0] + + @ calculate H^2 + vext.8 $t0,$H,$H,#8 @ Karatsuba pre-processing + vpmull.p64 $Xl,$H,$H + veor $t0,$t0,$H + vpmull2.p64 $Xh,$H,$H + vpmull.p64 $Xm,$t0,$t0 + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $H2,$Xl,$t2 + + vext.8 $t1,$H2,$H2,#8 @ Karatsuba pre-processing + veor $t1,$t1,$H2 + vext.8 $Hhl,$t0,$t1,#8 @ pack Karatsuba pre-processed + vst1.64 {$Hhl-$H2},[x0] @ store Htable[1..2] + + ret +.size gcm_init_v8,.-gcm_init_v8 +___ +################################################################################ +# void gcm_gmult_v8(u64 Xi[2],const u128 Htable[16]); +# +# input: Xi - current hash value; +# Htable - table precomputed in gcm_init_v8; +# output: Xi - next hash value Xi; +# +$code.=<<___; +.global gcm_gmult_v8 +.type gcm_gmult_v8,%function +.align 4 +gcm_gmult_v8: + vld1.64 {$t1},[$Xi] @ load Xi + vmov.i8 $xC2,#0xe1 + vld1.64 {$H-$Hhl},[$Htbl] @ load twisted H, ... + vshl.u64 $xC2,$xC2,#57 +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vext.8 $IN,$t1,$t1,#8 + + 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 + vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi) + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl +#endif + vext.8 $Xl,$Xl,$Xl,#8 + vst1.64 {$Xl},[$Xi] @ write out Xi + + ret +.size gcm_gmult_v8,.-gcm_gmult_v8 +___ +################################################################################ +# void gcm_ghash_v8(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len); +# +# input: table precomputed in gcm_init_v8; +# current hash value Xi; +# pointer to input data; +# length of input data in bytes, but divisible by block size; +# output: next hash value Xi; +# +$code.=<<___; +.global gcm_ghash_v8 +.type gcm_ghash_v8,%function +.align 4 +gcm_ghash_v8: +___ +$code.=<<___ if ($flavour !~ /64/); + vstmdb sp!,{d8-d15} @ 32-bit ABI says so +___ +$code.=<<___; + vld1.64 {$Xl},[$Xi] @ load [rotated] Xi + @ "[rotated]" means that + @ loaded value would have + @ to be rotated in order to + @ make it appear as in + @ alorithm specification + subs $len,$len,#32 @ see if $len is 32 or larger + mov $inc,#16 @ $inc is used as post- + @ increment for input pointer; + @ as loop is modulo-scheduled + @ $inc is zeroed just in time + @ to preclude oversteping + @ inp[len], which means that + @ last block[s] are actually + @ loaded twice, but last + @ copy is not processed + vld1.64 {$H-$Hhl},[$Htbl],#32 @ load twisted H, ..., H^2 + vmov.i8 $xC2,#0xe1 + vld1.64 {$H2},[$Htbl] + cclr $inc,eq @ is it time to zero $inc? + vext.8 $Xl,$Xl,$Xl,#8 @ rotate Xi + vld1.64 {$t0},[$inp],#16 @ load [rotated] I[0] + vshl.u64 $xC2,$xC2,#57 @ compose 0xc2.0 constant +#ifndef __ARMEB__ + vrev64.8 $t0,$t0 + vrev64.8 $Xl,$Xl +#endif + vext.8 $IN,$t0,$t0,#8 @ rotate I[0] + b.lo .Lodd_tail_v8 @ $len was less than 32 +___ +{ my ($Xln,$Xmn,$Xhn,$In) = map("q$_",(4..7)); + ####### + # 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 + # +$code.=<<___; + vld1.64 {$t1},[$inp],$inc @ load [rotated] I[1] +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vext.8 $In,$t1,$t1,#8 + veor $IN,$IN,$Xl @ I[i]^=Xi + vpmull.p64 $Xln,$H,$In @ H·Ii+1 + veor $t1,$t1,$In @ Karatsuba pre-processing + vpmull2.p64 $Xhn,$H,$In + b .Loop_mod2x_v8 + +.align 4 +.Loop_mod2x_v8: + vext.8 $t2,$IN,$IN,#8 + subs $len,$len,#32 @ is there more data? + vpmull.p64 $Xl,$H2,$IN @ H^2.lo·Xi.lo + cclr $inc,lo @ is it time to zero $inc? + + vpmull.p64 $Xmn,$Hhl,$t1 + veor $t2,$t2,$IN @ Karatsuba pre-processing + vpmull2.p64 $Xh,$H2,$IN @ H^2.hi·Xi.hi + veor $Xl,$Xl,$Xln @ accumulate + vpmull2.p64 $Xm,$Hhl,$t2 @ (H^2.lo+H^2.hi)·(Xi.lo+Xi.hi) + vld1.64 {$t0},[$inp],$inc @ load [rotated] I[i+2] + + veor $Xh,$Xh,$Xhn + cclr $inc,eq @ is it time to zero $inc? + veor $Xm,$Xm,$Xmn + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + vld1.64 {$t1},[$inp],$inc @ load [rotated] I[i+3] +#ifndef __ARMEB__ + vrev64.8 $t0,$t0 +#endif + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vext.8 $In,$t1,$t1,#8 + vext.8 $IN,$t0,$t0,#8 + veor $Xl,$Xm,$t2 + vpmull.p64 $Xln,$H,$In @ H·Ii+1 + veor $IN,$IN,$Xh @ accumulate $IN early + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $IN,$IN,$t2 + veor $t1,$t1,$In @ Karatsuba pre-processing + veor $IN,$IN,$Xl + vpmull2.p64 $Xhn,$H,$In + b.hs .Loop_mod2x_v8 @ there was at least 32 more bytes + + veor $Xh,$Xh,$t2 + vext.8 $IN,$t0,$t0,#8 @ re-construct $IN + adds $len,$len,#32 @ re-construct $len + veor $Xl,$Xl,$Xh @ re-construct $Xl + b.eq .Ldone_v8 @ is $len zero? +___ +} +$code.=<<___; +.Lodd_tail_v8: + vext.8 $t2,$Xl,$Xl,#8 + veor $IN,$IN,$Xl @ inp^=Xi + veor $t1,$t0,$t2 @ $t1 is rotated inp^Xi + + 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 + vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi) + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + +.Ldone_v8: +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl +#endif + vext.8 $Xl,$Xl,$Xl,#8 + vst1.64 {$Xl},[$Xi] @ write out Xi + +___ +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} @ 32-bit ABI says so +___ +$code.=<<___; + ret +.size gcm_ghash_v8,.-gcm_ghash_v8 +___ +} +$code.=<<___; +.asciz "GHASH for ARMv8, CRYPTOGAMS by " +.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/external/boringssl/crypto/modes/cbc.c b/external/boringssl/crypto/modes/cbc.c new file mode 100644 index 0000000000..e41f2b497f --- /dev/null +++ b/external/boringssl/crypto/modes/cbc.c @@ -0,0 +1,216 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include +#include + +#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(key != NULL && ivec != NULL); + assert(len == 0 || (in != NULL && out != NULL)); + + 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(key != NULL && ivec != NULL); + assert(len == 0 || (in != NULL && out != NULL)); + + const uintptr_t inptr = (uintptr_t) in; + const uintptr_t outptr = (uintptr_t) out; + /* If |in| and |out| alias, |in| must be ahead. */ + assert(inptr >= outptr || inptr + len <= outptr); + + if ((inptr >= 32 && outptr <= inptr - 32) || inptr < outptr) { + /* If |out| is at least two blocks behind |in| or completely disjoint, there + * is no need to decrypt to a temporary block. */ + 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 { + /* |out| is less than two blocks behind |in|. Decrypting an input block + * directly to |out| would overwrite a ciphertext block before it is used as + * the next block's IV. Decrypt to a temporary block instead. */ + 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/external/boringssl/crypto/modes/cfb.c b/external/boringssl/crypto/modes/cfb.c new file mode 100644 index 0000000000..51b883e8d4 --- /dev/null +++ b/external/boringssl/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 + +#include +#include + +#include "internal.h" + + +OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size); + +void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], unsigned *num, + int enc, block128_f block) { + size_t l = 0; + + assert(in && out && key && ivec && num); + + unsigned 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], unsigned *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], unsigned *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/external/boringssl/crypto/modes/ctr.c b/external/boringssl/crypto/modes/ctr.c new file mode 100644 index 0000000000..b84e72c59a --- /dev/null +++ b/external/boringssl/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 + +#include +#include + +#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, c = 1; + + do { + --n; + c += counter[n]; + counter[n] = (uint8_t) c; + c >>= 8; + } while (n); +} + +OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size); + +/* 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(key && ecount_buf && num); + assert(len == 0 || (in && out)); + assert(*num < 16); + + 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)ecount_buf) % 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 = 0; n < 16; n += sizeof(size_t)) { + *(size_t *)(out + n) = *(const size_t *)(in + n) ^ + *(const 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, c = 1; + + do { + --n; + c += counter[n]; + counter[n] = (uint8_t) c; + c >>= 8; + } 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(key && ecount_buf && num); + assert(len == 0 || (in && out)); + 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/external/boringssl/crypto/modes/gcm.c b/external/boringssl/crypto/modes/gcm.c new file mode 100644 index 0000000000..b8571313d4 --- /dev/null +++ b/external/boringssl/crypto/modes/gcm.c @@ -0,0 +1,1272 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include +#include + +#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 = UINT64_C(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) + +// kSizeTWithoutLower4Bits is a mask that can be used to zero the lower four +// bits of a |size_t|. +static const size_t kSizeTWithoutLower4Bits = (size_t) -16; + +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 *in, + size_t len); +#define AESNI_GCM +static int aesni_gcm_enabled(GCM128_CONTEXT *ctx, ctr128_f stream) { + return stream == aesni_ctr32_encrypt_blocks && + ctx->ghash == gcm_ghash_avx; +} + +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); +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); +#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 +#if __ARM_ARCH__ >= 7 +#define GHASH_ASM_ARM +#define GCM_FUNCREF_4BIT + +static int pmull_capable(void) { + return CRYPTO_is_ARMv8_PMULL_capable(); +} + +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(void) { + 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(void) { + return 0; +} +static void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) { + abort(); +} +static void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) { + abort(); +} +static 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 + +void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key, + block128_f block) { + const union { + long one; + char little; + } is_endian = {1}; + + memset(ctx, 0, sizeof(*ctx)); + ctx->block = block; + + (*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 void *key, + 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, 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 > (UINT64_C(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 + i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + 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 void *key, + 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; +#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 > ((UINT64_C(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 void *key, + 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; +#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 > ((UINT64_C(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; + } + i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + 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 void *key, + 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; + uint64_t mlen = ctx->len.u[1]; +#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 > ((UINT64_C(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; + } + + 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(AESNI_GCM) + if (aesni_gcm_enabled(ctx, stream)) { + /* |aesni_gcm_encrypt| may not process all the input given to it. It may + * not process *any* of its input if it is deemed too small. */ + size_t bulk = aesni_gcm_encrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); + in += bulk; + out += bulk; + len -= bulk; + } +#endif + + if (is_endian.little) { + ctr = GETU32(ctx->Yi.c + 12); + } else { + ctr = ctx->Yi.d[3]; + } + +#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 + size_t i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + 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 void *key, + 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; + uint64_t mlen = ctx->len.u[1]; +#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 > ((UINT64_C(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; + } + + 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(AESNI_GCM) + if (aesni_gcm_enabled(ctx, stream)) { + /* |aesni_gcm_decrypt| may not process all the input given to it. It may + * not process *any* of its input if it is deemed too small. */ + size_t bulk = aesni_gcm_decrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); + in += bulk; + out += bulk; + len -= bulk; + } +#endif + + if (is_endian.little) { + ctr = GETU32(ctx->Yi.c + 12); + } else { + ctr = ctx->Yi.d[3]; + } + +#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 + size_t i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + 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)); +} + +#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/external/boringssl/crypto/modes/gcm_test.c b/external/boringssl/crypto/modes/gcm_test.c new file mode 100644 index 0000000000..19c295b54e --- /dev/null +++ b/external/boringssl/crypto/modes/gcm_test.c @@ -0,0 +1,411 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include +#include + +#include +#include +#include + +#include "internal.h" +#include "../test/test_util.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 %zu.\n", + test_num, description, i); + goto err; + } + buf[i/2] = (v << 4) | v2; + } + + *out = buf; + *out_len = len/2; + return 1; + +err: + OPENSSL_free(buf); + return 0; +} + +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 (plaintext_len != 0 && out == NULL) { + goto out; + } + 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, &aes_key, 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, &aes_key, 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(stderr, "got :", out, plaintext_len); + hexdump(stderr, "want:", ciphertext, plaintext_len); + goto out; + } + + CRYPTO_gcm128_setiv(&ctx, &aes_key, 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, &aes_key, 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: + OPENSSL_free(key); + OPENSSL_free(plaintext); + OPENSSL_free(additional_data); + OPENSSL_free(nonce); + OPENSSL_free(ciphertext); + OPENSSL_free(tag); + 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/external/boringssl/crypto/modes/internal.h b/external/boringssl/crypto/modes/internal.h new file mode 100644 index 0000000000..430d0401e6 --- /dev/null +++ b/external/boringssl/crypto/modes/internal.h @@ -0,0 +1,358 @@ +/* ==================================================================== + * 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 + +#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 +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#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 + + +/* 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); + +/* GCM definitions */ +typedef struct { uint64_t hi,lo; } u128; + +/* This differs from upstream's |gcm128_context| in that it does not have the + * |key| pointer, in order to make it |memcpy|-friendly. Rather the key is + * passed into each call that needs it. */ +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; +}; + +#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 + + +/* 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. */ +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 *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. */ +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 *num, + ctr128_f ctr); + + +/* GCM. + * + * This API differs from the upstream API slightly. The |GCM128_CONTEXT| does + * not have a |key| pointer that points to the key as upstream's version does. + * Instead, every function takes a |key| parameter. This way |GCM128_CONTEXT| + * can be safely copied. */ + +typedef struct gcm128_context GCM128_CONTEXT; + +/* CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with + * the given key. */ +OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key, + block128_f block); + +/* CRYPTO_gcm128_setiv sets the IV (nonce) for |ctx|. The |key| must be the + * same key that was passed to |CRYPTO_gcm128_init|. */ +OPENSSL_EXPORT void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *iv, size_t iv_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|. The |key| + * must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one + * on success and zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *in, uint8_t *out, + size_t len); + +/* CRYPTO_gcm128_decrypt decrypts |len| bytes from |in| to |out|. The |key| + * must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one + * on success and zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key, + 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|. The |key| must be the same key that was + * passed to |CRYPTO_gcm128_init|. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const void *key, + 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|. The |key| must be the same key that was + * passed to |CRYPTO_gcm128_init|. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const void *key, + 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); + + +/* 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], + unsigned *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], unsigned *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], unsigned *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], unsigned *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(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) +void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks, + const void *key, const uint8_t *ivec); +#endif + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_MODES_INTERNAL_H */ diff --git a/external/boringssl/crypto/modes/ofb.c b/external/boringssl/crypto/modes/ofb.c new file mode 100644 index 0000000000..2c5bdc9ab5 --- /dev/null +++ b/external/boringssl/crypto/modes/ofb.c @@ -0,0 +1,106 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include + +#include "internal.h" + + +OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size); + +void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], unsigned *num, + block128_f block) { + assert(in && out && key && ivec && num); + + unsigned 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/external/boringssl/crypto/newhope/CMakeLists.txt b/external/boringssl/crypto/newhope/CMakeLists.txt new file mode 100644 index 0000000000..0f080f8c5b --- /dev/null +++ b/external/boringssl/crypto/newhope/CMakeLists.txt @@ -0,0 +1,42 @@ +add_library( + newhope + + OBJECT + + error_correction.c + newhope.c + ntt.c + poly.c + precomp.c + reduce.c +) + +if(ENABLE_TESTS) +add_executable( + newhope_test + + newhope_test.cc + $ +) + +add_executable( + newhope_statistical_test + + newhope_statistical_test.cc + $ +) + +add_executable( + newhope_vectors_test + + newhope_vectors_test.cc + $ +) + +target_link_libraries(newhope_test crypto) +target_link_libraries(newhope_statistical_test crypto) +target_link_libraries(newhope_vectors_test crypto) +add_dependencies(all_tests newhope_test) +add_dependencies(all_tests newhope_statistical_test) +add_dependencies(all_tests newhope_vectors_test) +endif() diff --git a/external/boringssl/crypto/newhope/error_correction.c b/external/boringssl/crypto/newhope/error_correction.c new file mode 100644 index 0000000000..2b822b0b32 --- /dev/null +++ b/external/boringssl/crypto/newhope/error_correction.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include "internal.h" + + +/* See paper for details on the error reconciliation */ + +static int32_t abs_32(int32_t v) { + int32_t mask = v >> 31; + return (v ^ mask) - mask; +} + +static int32_t f(int32_t* v0, int32_t* v1, int32_t x) { + int32_t xit, t, r, b; + + /* Next 6 lines compute t = x/PARAM_Q */ + b = x * 2730; + t = b >> 25; + b = x - t * 12289; + b = 12288 - b; + b >>= 31; + t -= b; + + r = t & 1; + xit = (t >> 1); + *v0 = xit + r; /* v0 = round(x/(2*PARAM_Q)) */ + + t -= 1; + r = t & 1; + *v1 = (t >> 1) + r; + + return abs_32(x - ((*v0) * 2 * PARAM_Q)); +} + +static int32_t g(int32_t x) { + int32_t t, c, b; + + /* Next 6 lines compute t = x/(4*PARAM_Q); */ + b = x * 2730; + t = b >> 27; + b = x - t * 49156; + b = 49155 - b; + b >>= 31; + t -= b; + + c = t & 1; + t = (t >> 1) + c; /* t = round(x/(8*PARAM_Q)) */ + + t *= 8 * PARAM_Q; + + return abs_32(t - x); +} + +static int16_t LDDecode(int32_t xi0, int32_t xi1, int32_t xi2, int32_t xi3) { + int32_t t; + + t = g(xi0); + t += g(xi1); + t += g(xi2); + t += g(xi3); + + t -= 8 * PARAM_Q; + t >>= 31; + return t & 1; +} + +void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v, + const uint8_t rand[32]) { + int32_t v0[4], v1[4], v_tmp[4], k; + uint8_t rbit; + unsigned i; + + for (i = 0; i < 256; i++) { + rbit = (rand[i >> 3] >> (i & 7)) & 1; + + k = f(v0 + 0, v1 + 0, 8 * v->coeffs[0 + i] + 4 * rbit); + k += f(v0 + 1, v1 + 1, 8 * v->coeffs[256 + i] + 4 * rbit); + k += f(v0 + 2, v1 + 2, 8 * v->coeffs[512 + i] + 4 * rbit); + k += f(v0 + 3, v1 + 3, 8 * v->coeffs[768 + i] + 4 * rbit); + + k = (2 * PARAM_Q - 1 - k) >> 31; + + v_tmp[0] = ((~k) & v0[0]) ^ (k & v1[0]); + v_tmp[1] = ((~k) & v0[1]) ^ (k & v1[1]); + v_tmp[2] = ((~k) & v0[2]) ^ (k & v1[2]); + v_tmp[3] = ((~k) & v0[3]) ^ (k & v1[3]); + + c->coeffs[0 + i] = (v_tmp[0] - v_tmp[3]) & 3; + c->coeffs[256 + i] = (v_tmp[1] - v_tmp[3]) & 3; + c->coeffs[512 + i] = (v_tmp[2] - v_tmp[3]) & 3; + c->coeffs[768 + i] = (-k + 2 * v_tmp[3]) & 3; + } +} + +void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v, + const NEWHOPE_POLY* c) { + int i; + int32_t tmp[4]; + + memset(key, 0, NEWHOPE_KEY_LENGTH); + + for (i = 0; i < 256; i++) { + tmp[0] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[0 + i] - + PARAM_Q * (2 * c->coeffs[0 + i] + c->coeffs[768 + i]); + tmp[1] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[256 + i] - + PARAM_Q * (2 * c->coeffs[256 + i] + c->coeffs[768 + i]); + tmp[2] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[512 + i] - + PARAM_Q * (2 * c->coeffs[512 + i] + c->coeffs[768 + i]); + tmp[3] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[768 + i] - + PARAM_Q * (c->coeffs[768 + i]); + + key[i >> 3] |= LDDecode(tmp[0], tmp[1], tmp[2], tmp[3]) << (i & 7); + } +} diff --git a/external/boringssl/crypto/newhope/internal.h b/external/boringssl/crypto/newhope/internal.h new file mode 100644 index 0000000000..eb170c0661 --- /dev/null +++ b/external/boringssl/crypto/newhope/internal.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2016, 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_NEWHOPE_INTERNAL_H +#define OPENSSL_HEADER_NEWHOPE_INTERNAL_H + +#include +#include + +#include "../internal.h" + + +/* The number of polynomial coefficients. */ +#define PARAM_N 1024 + +/* The width the noise distribution. */ +#define PARAM_K 16 + +/* Modulus. */ +#define PARAM_Q 12289 + +/* Polynomial coefficients in unpacked form. */ +struct newhope_poly_st { + uint16_t coeffs[PARAM_N]; +}; + +/* SEED_LENGTH is the length of the AES-CTR seed used to derive a polynomial. */ +#define SEED_LENGTH 32 + +/* newhope_poly_uniform generates the polynomial |a| using AES-CTR mode with the + * seed + * |seed|. (In the reference implementation this was done with SHAKE-128.) */ +void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed); + +void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v, + const uint8_t rbits[32]); + +/* newhope_reconcile performs the error-reconciliation step using the input |v| + * and + * reconciliation data |c|, writing the resulting key to |key|. */ +void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v, + const NEWHOPE_POLY* c); + +/* newhope_poly_invntt performs the inverse of NTT(r) in-place. */ +void newhope_poly_invntt(NEWHOPE_POLY* r); + +void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b); +void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b); + +uint16_t newhope_montgomery_reduce(uint32_t a); +uint16_t newhope_barrett_reduce(uint16_t a); + +void newhope_bitrev_vector(uint16_t* poly); +void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors); +void newhope_ntt(uint16_t* poly, const uint16_t* omegas); + + +#endif /* OPENSSL_HEADER_NEWHOPE_INTERNAL_H */ diff --git a/external/boringssl/crypto/newhope/newhope.c b/external/boringssl/crypto/newhope/newhope.c new file mode 100644 index 0000000000..7edb7eb7b3 --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope.c @@ -0,0 +1,174 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include "internal.h" + + +NEWHOPE_POLY *NEWHOPE_POLY_new(void) { + return (NEWHOPE_POLY *)OPENSSL_malloc(sizeof(NEWHOPE_POLY)); +} + +void NEWHOPE_POLY_free(NEWHOPE_POLY *p) { OPENSSL_free(p); } + +/* Encodes reconciliation data from |c| into |r|. */ +static void encode_rec(const NEWHOPE_POLY *c, uint8_t *r) { + int i; + for (i = 0; i < PARAM_N / 4; i++) { + r[i] = c->coeffs[4 * i] | (c->coeffs[4 * i + 1] << 2) | + (c->coeffs[4 * i + 2] << 4) | (c->coeffs[4 * i + 3] << 6); + } +} + +/* Decodes reconciliation data from |r| into |c|. */ +static void decode_rec(const uint8_t *r, NEWHOPE_POLY *c) { + int i; + for (i = 0; i < PARAM_N / 4; i++) { + c->coeffs[4 * i + 0] = r[i] & 0x03; + c->coeffs[4 * i + 1] = (r[i] >> 2) & 0x03; + c->coeffs[4 * i + 2] = (r[i] >> 4) & 0x03; + c->coeffs[4 * i + 3] = (r[i] >> 6); + } +} + +void NEWHOPE_offer(uint8_t *offermsg, NEWHOPE_POLY *s) { + NEWHOPE_POLY_noise_ntt(s); + + /* The first part of the offer message is the seed, which compactly encodes + * a. */ + NEWHOPE_POLY a; + uint8_t *seed = &offermsg[NEWHOPE_POLY_LENGTH]; + RAND_bytes(seed, SEED_LENGTH); + newhope_poly_uniform(&a, seed); + + NEWHOPE_POLY e; + NEWHOPE_POLY_noise_ntt(&e); + + /* The second part of the offer message is the polynomial pk = a*s+e */ + NEWHOPE_POLY pk; + NEWHOPE_offer_computation(&pk, s, &e, &a); + NEWHOPE_POLY_tobytes(offermsg, &pk); +} + +int NEWHOPE_accept(uint8_t key[SHA256_DIGEST_LENGTH], + uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH], + const uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH], + size_t msg_len) { + if (msg_len != NEWHOPE_OFFERMSG_LENGTH) { + return 0; + } + + /* Decode the |offermsg|, generating the same |a| as the peer, from the peer's + * seed. */ + NEWHOPE_POLY pk, a; + NEWHOPE_offer_frommsg(&pk, &a, offermsg); + + /* Generate noise polynomials used to generate our key. */ + NEWHOPE_POLY sp, ep, epp; + NEWHOPE_POLY_noise_ntt(&sp); + NEWHOPE_POLY_noise_ntt(&ep); + NEWHOPE_POLY_noise(&epp); /* intentionally not NTT */ + + /* Generate random bytes used for reconciliation. (The reference + * implementation calls ChaCha20 here.) */ + uint8_t rand[32]; + RAND_bytes(rand, sizeof(rand)); + + /* Encode |bp| and |c| as the |acceptmsg|. */ + NEWHOPE_POLY bp, c; + uint8_t k[NEWHOPE_KEY_LENGTH]; + NEWHOPE_accept_computation(k, &bp, &c, &sp, &ep, &epp, rand, &pk, &a); + NEWHOPE_POLY_tobytes(acceptmsg, &bp); + encode_rec(&c, &acceptmsg[NEWHOPE_POLY_LENGTH]); + + SHA256_CTX ctx; + if (!SHA256_Init(&ctx) || + !SHA256_Update(&ctx, k, NEWHOPE_KEY_LENGTH) || + !SHA256_Final(key, &ctx)) { + return 0; + } + + return 1; +} + +int NEWHOPE_finish(uint8_t key[SHA256_DIGEST_LENGTH], const NEWHOPE_POLY *sk, + const uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH], + size_t msg_len) { + if (msg_len != NEWHOPE_ACCEPTMSG_LENGTH) { + return 0; + } + + /* Decode the accept message into |bp| and |c|. */ + NEWHOPE_POLY bp, c; + NEWHOPE_POLY_frombytes(&bp, acceptmsg); + decode_rec(&acceptmsg[NEWHOPE_POLY_LENGTH], &c); + + uint8_t k[NEWHOPE_KEY_LENGTH]; + NEWHOPE_finish_computation(k, sk, &bp, &c); + SHA256_CTX ctx; + if (!SHA256_Init(&ctx) || + !SHA256_Update(&ctx, k, NEWHOPE_KEY_LENGTH) || + !SHA256_Final(key, &ctx)) { + return 0; + } + + return 1; +} + +void NEWHOPE_offer_computation(NEWHOPE_POLY *out_pk, + const NEWHOPE_POLY *s, const NEWHOPE_POLY *e, + const NEWHOPE_POLY *a) { + NEWHOPE_POLY r; + newhope_poly_pointwise(&r, s, a); + newhope_poly_add(out_pk, e, &r); +} + +void NEWHOPE_accept_computation( + uint8_t k[NEWHOPE_KEY_LENGTH], NEWHOPE_POLY *bp, + NEWHOPE_POLY *reconciliation, + const NEWHOPE_POLY *sp, const NEWHOPE_POLY *ep, const NEWHOPE_POLY *epp, + const uint8_t rand[32], + const NEWHOPE_POLY *pk, const NEWHOPE_POLY *a) { + /* bp = a*s' + e' */ + newhope_poly_pointwise(bp, a, sp); + newhope_poly_add(bp, bp, ep); + + /* v = pk * s' + e'' */ + NEWHOPE_POLY v; + newhope_poly_pointwise(&v, pk, sp); + newhope_poly_invntt(&v); + newhope_poly_add(&v, &v, epp); + newhope_helprec(reconciliation, &v, rand); + newhope_reconcile(k, &v, reconciliation); +} + +void NEWHOPE_finish_computation(uint8_t k[NEWHOPE_KEY_LENGTH], + const NEWHOPE_POLY *sk, const NEWHOPE_POLY *bp, + const NEWHOPE_POLY *reconciliation) { + NEWHOPE_POLY v; + newhope_poly_pointwise(&v, sk, bp); + newhope_poly_invntt(&v); + newhope_reconcile(k, &v, reconciliation); +} + +void NEWHOPE_offer_frommsg(NEWHOPE_POLY *out_pk, NEWHOPE_POLY *out_a, + const uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH]) { + NEWHOPE_POLY_frombytes(out_pk, offermsg); + const uint8_t *seed = offermsg + NEWHOPE_POLY_LENGTH; + newhope_poly_uniform(out_a, seed); +} diff --git a/external/boringssl/crypto/newhope/newhope_statistical_test.cc b/external/boringssl/crypto/newhope/newhope_statistical_test.cc new file mode 100644 index 0000000000..44fac48a02 --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_statistical_test.cc @@ -0,0 +1,156 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include + +#include "../test/scoped_types.h" +#include "internal.h" + + +static const unsigned kNumTests = 1000; + +static bool TestNoise(void) { + printf("noise distribution:\n"); + + size_t buckets[1 + 2 * PARAM_K]; + memset(buckets, 0, sizeof(buckets)); + for (size_t i = 0; i < kNumTests; i++) { + NEWHOPE_POLY s; + NEWHOPE_POLY_noise(&s); + for (int j = 0; j < PARAM_N; j++) { + uint16_t value = (s.coeffs[j] + PARAM_K) % PARAM_Q; + buckets[value]++; + } + } + + int64_t sum = 0, square_sum = 0; + for (int64_t i = 0; i < 1 + 2 * PARAM_K; i++) { + sum += (i - PARAM_K) * (int64_t) buckets[i]; + square_sum += (i - PARAM_K) * (i - PARAM_K) * (int64_t) buckets[i]; + } + double mean = double(sum) / double(PARAM_N * kNumTests); + + double expected_variance = 0.5 * 0.5 * double(PARAM_K * 2); + double variance = double(square_sum) / double(PARAM_N * kNumTests) - mean * mean; + + for (size_t i = 0; i < 1 + 2 * PARAM_K; i++) { + std::string dots; + for (size_t j = 0; j < 79 * buckets[i] / buckets[PARAM_K]; j++) { + dots += "+"; + } + printf("%+zd\t%zd\t%s\n", i - PARAM_K, buckets[i], dots.c_str()); + } + printf("mean: got %f, want %f\n", mean, 0.0); + printf("variance: got %f, want %f\n", variance, expected_variance); + printf("\n"); + + if (mean < -0.5 || 0.5 < mean) { + fprintf(stderr, "mean out of range: %f\n", mean); + return false; + } + + if (variance < expected_variance - 1.0 || expected_variance + 1.0 < variance) { + fprintf(stderr, "variance out of range: got %f, want %f\n", variance, + expected_variance); + return false; + } + return true; +} + +static int Hamming32(const uint8_t key[NEWHOPE_KEY_LENGTH]) { + static int kHamming[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + }; + + int r = 0; + for(int i = 0; i < NEWHOPE_KEY_LENGTH; i++) { + r += kHamming[key[i]]; + } + return r; +} + +static bool TestKeys(void) { + printf("keys (prior to whitening):\n"); + + uint8_t key[NEWHOPE_KEY_LENGTH]; + uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH]; + + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()), pk(NEWHOPE_POLY_new()), + sp(NEWHOPE_POLY_new()), ep(NEWHOPE_POLY_new()), epp(NEWHOPE_POLY_new()), + a(NEWHOPE_POLY_new()), bp(NEWHOPE_POLY_new()), rec(NEWHOPE_POLY_new()); + + int ones = 0; + for (size_t i = 0; i < kNumTests; i++) { + NEWHOPE_offer(offermsg, sk.get()); + NEWHOPE_offer_frommsg(pk.get(), a.get(), offermsg); + + NEWHOPE_POLY_noise_ntt(sp.get()); + NEWHOPE_POLY_noise_ntt(ep.get()); + NEWHOPE_POLY_noise(epp.get()); /* intentionally not NTT */ + + uint8_t rand[32]; + RAND_bytes(rand, 32); + + NEWHOPE_accept_computation(key, bp.get(), rec.get(), + sp.get(), ep.get(), epp.get(), rand, + pk.get(), a.get()); + ones += Hamming32(key); + } + + int bits = NEWHOPE_KEY_LENGTH * 8 * kNumTests; + int diff = bits - 2 * ones; + double fraction = (double) abs(diff) / bits; + printf("ones: %d\n", ones); + printf("zeroes: %d\n", (bits - ones)); + printf("diff: got %d (%f), want 0\n", diff, fraction); + printf("\n"); + + if (fraction > 0.01) { + fprintf(stderr, "key bias is too high (%f)\n", fraction); + return false; + } + + return true; +} + +int main(void) { + if (!TestKeys() || + !TestNoise()) { + return 1; + } + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/newhope/newhope_test.cc b/external/boringssl/crypto/newhope/newhope_test.cc new file mode 100644 index 0000000000..6637393f66 --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_test.cc @@ -0,0 +1,142 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include + +#include "../test/scoped_types.h" +#include "internal.h" + + +// Set to 10 for quick execution. Tested up to 1,000,000. +static const int kNumTests = 10; + +static bool TestKeys(void) { + // Alice generates a public key. + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()); + uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH]; + NEWHOPE_offer(offer_msg, sk.get()); + + // Bob derives a secret key and creates a response. + uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH]; + uint8_t accept_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) { + fprintf(stderr, "ERROR accept key exchange failed\n"); + return false; + } + + // Alice uses Bob's response to get her secret key. + uint8_t offer_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) { + fprintf(stderr, "ERROR finish key exchange failed\n"); + return false; + } + + if (memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH) != 0) { + fprintf(stderr, "ERROR keys did not agree\n"); + return false; + } + + return true; +} + +static bool TestInvalidSK(void) { + // Alice generates a public key. + uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH]; + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()); + NEWHOPE_offer(offer_msg, sk.get()); + + // Bob derives a secret key and creates a response. + uint8_t accept_key[SHA256_DIGEST_LENGTH]; + uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH]; + if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) { + fprintf(stderr, "ERROR accept key exchange failed\n"); + return false; + } + + // Corrupt the secret key. It turns out that you need to corrupt a lot of + // bits to ensure that the key exchange always fails! + sk->coeffs[PARAM_N - 1] = 0; + sk->coeffs[PARAM_N - 2] = 0; + sk->coeffs[PARAM_N - 3] = 0; + sk->coeffs[PARAM_N - 4] = 0; + + // Alice uses Bob's response to get her secret key. + uint8_t offer_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) { + fprintf(stderr, "ERROR finish key exchange failed\n"); + return false; + } + + if (memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH) == 0) { + fprintf(stderr, "ERROR keys agreed despite corrupt sk\n"); + return false; + } + + return true; +} + +static bool TestInvalidAcceptMsg(void) { + // Alice generates a public key. + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()); + uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH]; + NEWHOPE_offer(offer_msg, sk.get()); + + // Bob derives a secret key and creates a response. + uint8_t accept_key[SHA256_DIGEST_LENGTH]; + uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH]; + if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) { + fprintf(stderr, "ERROR accept key exchange failed\n"); + return false; + } + + // Corrupt the (polynomial part of the) accept message. It turns out that + // you need to corrupt a lot of bits to ensure that the key exchange always + // fails! + accept_msg[PARAM_N - 1] = 0; + accept_msg[PARAM_N - 2] = 0; + accept_msg[PARAM_N - 3] = 0; + accept_msg[PARAM_N - 4] = 0; + + // Alice uses Bob's response to get her secret key. + uint8_t offer_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) { + fprintf(stderr, "ERROR finish key exchange failed\n"); + return false; + } + + if (!memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH)) { + fprintf(stderr, "ERROR keys agreed despite corrupt accept message\n"); + return false; + } + + return true; +} + +int main(void) { + for (int i = 0; i < kNumTests; i++) { + if (!TestKeys() || + !TestInvalidSK() || + !TestInvalidAcceptMsg()) { + return 1; + } + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/newhope/newhope_tests.txt.REMOVED.git-id b/external/boringssl/crypto/newhope/newhope_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..37d78c41dd --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +20d9c0371eca2e6a7a8d730e7c3c07698c5f5281 \ No newline at end of file diff --git a/external/boringssl/crypto/newhope/newhope_vectors_test.cc b/external/boringssl/crypto/newhope/newhope_vectors_test.cc new file mode 100644 index 0000000000..fe84cd4b5e --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_vectors_test.cc @@ -0,0 +1,122 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" +#include "internal.h" + + +static bool TestNewhope(FileTest *t, void *arg) { + ScopedNEWHOPE_POLY a(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY s(NEWHOPE_POLY_new()), sp(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY e(NEWHOPE_POLY_new()), ep(NEWHOPE_POLY_new()), + epp(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY in_pk(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY in_rec(NEWHOPE_POLY_new()); + + if (t->GetType() == "InRandA") { + std::vector a_bytes, s_bytes, e_bytes, expected_pk; + if (!t->GetBytes(&a_bytes, "InRandA") || + !t->GetBytes(&s_bytes, "InNoiseS") || + !t->GetBytes(&e_bytes, "InNoiseE") || + !t->GetBytes(&expected_pk, "OutPK")) { + return false; + } + NEWHOPE_POLY_frombytes(a.get(), a_bytes.data()); + NEWHOPE_POLY_frombytes(s.get(), s_bytes.data()); + NEWHOPE_POLY_frombytes(e.get(), e_bytes.data()); + + NEWHOPE_POLY pk; + NEWHOPE_offer_computation(&pk, s.get(), e.get(), a.get()); + + uint8_t pk_bytes[NEWHOPE_POLY_LENGTH]; + NEWHOPE_POLY_tobytes(pk_bytes, &pk); + return t->ExpectBytesEqual(expected_pk.data(), expected_pk.size(), + pk_bytes, NEWHOPE_POLY_LENGTH); + } else if (t->GetType() == "InPK") { + std::vector rand, in_pk_bytes, a_bytes, sp_bytes, ep_bytes, + epp_bytes, expected_pk, expected_rec, expected_key; + if (!t->GetBytes(&in_pk_bytes, "InPK") || + !t->GetBytes(&rand, "InRand") || + !t->GetBytes(&a_bytes, "InA") || + !t->GetBytes(&sp_bytes, "InNoiseSP") || + !t->GetBytes(&ep_bytes, "InNoiseEP") || + !t->GetBytes(&epp_bytes, "InNoiseEPP") || + !t->GetBytes(&expected_pk, "OutPK") || + !t->GetBytes(&expected_rec, "OutRec") || + !t->GetBytes(&expected_key, "Key")) { + return false; + } + NEWHOPE_POLY_frombytes(in_pk.get(), in_pk_bytes.data()); + NEWHOPE_POLY_frombytes(a.get(), a_bytes.data()); + NEWHOPE_POLY_frombytes(sp.get(), sp_bytes.data()); + NEWHOPE_POLY_frombytes(ep.get(), ep_bytes.data()); + NEWHOPE_POLY_frombytes(epp.get(), epp_bytes.data()); + + uint8_t key[NEWHOPE_KEY_LENGTH]; + NEWHOPE_POLY pk, rec; + NEWHOPE_accept_computation(key, &pk, &rec, + sp.get(), ep.get(), epp.get(), + rand.data(), in_pk.get(), a.get()); + + uint8_t pk_bytes[NEWHOPE_POLY_LENGTH], rec_bytes[NEWHOPE_POLY_LENGTH]; + NEWHOPE_POLY_tobytes(pk_bytes, &pk); + NEWHOPE_POLY_tobytes(rec_bytes, &rec); + return + t->ExpectBytesEqual(expected_key.data(), expected_key.size(), + key, NEWHOPE_KEY_LENGTH) && + t->ExpectBytesEqual(expected_pk.data(), expected_pk.size(), + pk_bytes, NEWHOPE_POLY_LENGTH) && + t->ExpectBytesEqual(expected_rec.data(), expected_rec.size(), + rec_bytes, NEWHOPE_POLY_LENGTH); + } else if (t->GetType() == "InNoiseS") { + std::vector s_bytes, in_pk_bytes, in_rec_bytes, expected_key; + if (!t->GetBytes(&s_bytes, "InNoiseS") || + !t->GetBytes(&in_pk_bytes, "InPK") || + !t->GetBytes(&in_rec_bytes, "InRec") || + !t->GetBytes(&expected_key, "Key")) { + return false; + } + NEWHOPE_POLY_frombytes(s.get(), s_bytes.data()); + NEWHOPE_POLY_frombytes(in_pk.get(), in_pk_bytes.data()); + NEWHOPE_POLY_frombytes(in_rec.get(), in_rec_bytes.data()); + + uint8_t key[NEWHOPE_KEY_LENGTH]; + NEWHOPE_finish_computation(key, s.get(), in_pk.get(), in_rec.get()); + + return t->ExpectBytesEqual(expected_key.data(), expected_key.size(), key, + NEWHOPE_KEY_LENGTH); + } else { + t->PrintLine("Unknown test '%s'", t->GetType().c_str()); + return false; + } +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestNewhope, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/newhope/ntt.c b/external/boringssl/crypto/newhope/ntt.c new file mode 100644 index 0000000000..163a9d1a0c --- /dev/null +++ b/external/boringssl/crypto/newhope/ntt.c @@ -0,0 +1,148 @@ +/* Copyright (c) 2016, 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 "internal.h" + + +static uint16_t bitrev_table[1024] = { + 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704, + 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864, + 224, 736, 480, 992, 16, 528, 272, 784, 144, 656, 400, 912, 80, 592, + 336, 848, 208, 720, 464, 976, 48, 560, 304, 816, 176, 688, 432, 944, + 112, 624, 368, 880, 240, 752, 496, 1008, 8, 520, 264, 776, 136, 648, + 392, 904, 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808, + 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, 24, 536, + 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, 216, 728, 472, 984, + 56, 568, 312, 824, 184, 696, 440, 952, 120, 632, 376, 888, 248, 760, + 504, 1016, 4, 516, 260, 772, 132, 644, 388, 900, 68, 580, 324, 836, + 196, 708, 452, 964, 36, 548, 292, 804, 164, 676, 420, 932, 100, 612, + 356, 868, 228, 740, 484, 996, 20, 532, 276, 788, 148, 660, 404, 916, + 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, 180, 692, + 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, 12, 524, 268, 780, + 140, 652, 396, 908, 76, 588, 332, 844, 204, 716, 460, 972, 44, 556, + 300, 812, 172, 684, 428, 940, 108, 620, 364, 876, 236, 748, 492, 1004, + 28, 540, 284, 796, 156, 668, 412, 924, 92, 604, 348, 860, 220, 732, + 476, 988, 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892, + 252, 764, 508, 1020, 2, 514, 258, 770, 130, 642, 386, 898, 66, 578, + 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, 162, 674, 418, 930, + 98, 610, 354, 866, 226, 738, 482, 994, 18, 530, 274, 786, 146, 658, + 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50, 562, 306, 818, + 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498, 1010, 10, 522, + 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970, + 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, 234, 746, + 490, 1002, 26, 538, 282, 794, 154, 666, 410, 922, 90, 602, 346, 858, + 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442, 954, 122, 634, + 378, 890, 250, 762, 506, 1018, 6, 518, 262, 774, 134, 646, 390, 902, + 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806, 166, 678, + 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, 22, 534, 278, 790, + 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54, 566, + 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502, 1014, + 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206, 718, + 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366, 878, + 238, 750, 494, 1006, 30, 542, 286, 798, 158, 670, 414, 926, 94, 606, + 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958, + 126, 638, 382, 894, 254, 766, 510, 1022, 1, 513, 257, 769, 129, 641, + 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801, + 161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, 17, 529, + 273, 785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977, + 49, 561, 305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753, + 497, 1009, 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841, + 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617, + 361, 873, 233, 745, 489, 1001, 25, 537, 281, 793, 153, 665, 409, 921, + 89, 601, 345, 857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697, + 441, 953, 121, 633, 377, 889, 249, 761, 505, 1017, 5, 517, 261, 773, + 133, 645, 389, 901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549, + 293, 805, 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997, + 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, 213, 725, + 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, 117, 629, 373, 885, + 245, 757, 501, 1013, 13, 525, 269, 781, 141, 653, 397, 909, 77, 589, + 333, 845, 205, 717, 461, 973, 45, 557, 301, 813, 173, 685, 429, 941, + 109, 621, 365, 877, 237, 749, 493, 1005, 29, 541, 285, 797, 157, 669, + 413, 925, 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829, + 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, 3, 515, + 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, 195, 707, 451, 963, + 35, 547, 291, 803, 163, 675, 419, 931, 99, 611, 355, 867, 227, 739, + 483, 995, 19, 531, 275, 787, 147, 659, 403, 915, 83, 595, 339, 851, + 211, 723, 467, 979, 51, 563, 307, 819, 179, 691, 435, 947, 115, 627, + 371, 883, 243, 755, 499, 1011, 11, 523, 267, 779, 139, 651, 395, 907, + 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, 171, 683, + 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, 27, 539, 283, 795, + 155, 667, 411, 923, 91, 603, 347, 859, 219, 731, 475, 987, 59, 571, + 315, 827, 187, 699, 443, 955, 123, 635, 379, 891, 251, 763, 507, 1019, + 7, 519, 263, 775, 135, 647, 391, 903, 71, 583, 327, 839, 199, 711, + 455, 967, 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871, + 231, 743, 487, 999, 23, 535, 279, 791, 151, 663, 407, 919, 87, 599, + 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183, 695, 439, 951, + 119, 631, 375, 887, 247, 759, 503, 1015, 15, 527, 271, 783, 143, 655, + 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559, 303, 815, + 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007, 31, 543, + 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991, + 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255, 767, + 511, 1023}; + +void newhope_bitrev_vector(uint16_t* poly) { + unsigned int i, r; + uint16_t tmp; + + for (i = 0; i < PARAM_N; i++) { + r = bitrev_table[i]; + if (i < r) { + tmp = poly[i]; + poly[i] = poly[r]; + poly[r] = tmp; + } + } +} + +void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors) { + unsigned int i; + + for (i = 0; i < PARAM_N; i++) { + poly[i] = newhope_montgomery_reduce((poly[i] * factors[i])); + } +} + +/* GS_bo_to_no; omegas need to be in Montgomery domain */ +void newhope_ntt(uint16_t* a, const uint16_t* omega) { + int i, start, j, jTwiddle, distance; + uint16_t temp, W; + + for (i = 0; i < 10; i += 2) { + /* Even level */ + distance = (1 << i); + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < PARAM_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]); /* Omit reduction (be lazy) */ + a[j + distance] = newhope_montgomery_reduce( + (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance]))); + } + } + + /* Odd level */ + distance <<= 1; + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < PARAM_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = newhope_barrett_reduce((temp + a[j + distance])); + a[j + distance] = newhope_montgomery_reduce( + (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance]))); + } + } + } +} diff --git a/external/boringssl/crypto/newhope/poly.c b/external/boringssl/crypto/newhope/poly.c new file mode 100644 index 0000000000..44cd3839bd --- /dev/null +++ b/external/boringssl/crypto/newhope/poly.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + +#include "internal.h" + + +extern uint16_t newhope_omegas_montgomery[]; +extern uint16_t newhope_omegas_inv_montgomery[]; + +extern uint16_t newhope_psis_bitrev_montgomery[]; +extern uint16_t newhope_psis_inv_montgomery[]; + +void NEWHOPE_POLY_frombytes(NEWHOPE_POLY* r, const uint8_t* a) { + int i; + for (i = 0; i < PARAM_N / 4; i++) { + r->coeffs[4 * i + 0] = + a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8); + r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) | + (((uint16_t)a[7 * i + 2]) << 2) | + (((uint16_t)a[7 * i + 3] & 0x0f) << 10); + r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) | + (((uint16_t)a[7 * i + 4]) << 4) | + (((uint16_t)a[7 * i + 5] & 0x03) << 12); + r->coeffs[4 * i + 3] = + (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6); + } +} + +void NEWHOPE_POLY_tobytes(uint8_t* r, const NEWHOPE_POLY* p) { + int i; + uint16_t t0, t1, t2, t3, m; + int16_t c; + for (i = 0; i < PARAM_N / 4; i++) { + t0 = newhope_barrett_reduce( + p->coeffs[4 * i + 0]); /* Make sure that coefficients + have only 14 bits */ + t1 = newhope_barrett_reduce(p->coeffs[4 * i + 1]); + t2 = newhope_barrett_reduce(p->coeffs[4 * i + 2]); + t3 = newhope_barrett_reduce(p->coeffs[4 * i + 3]); + + m = t0 - PARAM_Q; + c = m; + c >>= 15; + t0 = m ^ ((t0 ^ m) & c); /* Make sure that coefficients are in [0,q] */ + + m = t1 - PARAM_Q; + c = m; + c >>= 15; + t1 = m ^ ((t1 ^ m) & c); /* >= 15; + t2 = m ^ ((t2 ^ m) & c); /* >= 15; + t3 = m ^ ((t3 ^ m) & c); /* Make sure that coefficients are in [0,q] */ + + r[7 * i + 0] = t0 & 0xff; + r[7 * i + 1] = (t0 >> 8) | (t1 << 6); + r[7 * i + 2] = (t1 >> 2); + r[7 * i + 3] = (t1 >> 10) | (t2 << 4); + r[7 * i + 4] = (t2 >> 4); + r[7 * i + 5] = (t2 >> 12) | (t3 << 2); + r[7 * i + 6] = (t3 >> 6); + } +} + +void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed) { +/* The reference implementation uses SHAKE-128 here; this implementation uses + * AES-CTR. Use half the seed for the initialization vector and half for the + * key. */ +#if SEED_LENGTH != 2 * AES_BLOCK_SIZE +#error "2 * seed length != AES_BLOCK_SIZE" +#endif + uint8_t ivec[AES_BLOCK_SIZE]; + memcpy(ivec, &seed[SEED_LENGTH / 2], SEED_LENGTH / 2); + AES_KEY key; + AES_set_encrypt_key(seed, 8 * SEED_LENGTH / 2, &key); + + /* AES state. */ + uint8_t ecount[AES_BLOCK_SIZE]; + memset(ecount, 0, AES_BLOCK_SIZE); + + /* Encrypt a block of zeros just to get the random bytes. With luck, 2688 + * bytes is enough. */ + uint8_t buf[AES_BLOCK_SIZE * 168]; + memset(buf, 0, sizeof(buf)); + + unsigned int block_num = 0; + AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num); + + size_t pos = 0, coeff_num = 0; + while (coeff_num < PARAM_N) { + /* Specialized for q = 12889 */ + uint16_t val = (buf[pos] | ((uint16_t)buf[pos + 1] << 8)) & 0x3fff; + if (val < PARAM_Q) { + a->coeffs[coeff_num++] = val; + } + + pos += 2; + if (pos > sizeof(buf) - 2) { + memset(buf, 0, sizeof(buf)); + AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num); + pos = 0; + } + } +} + +void NEWHOPE_POLY_noise(NEWHOPE_POLY* r) { +#if PARAM_K != 16 +#error "poly_getnoise in poly.c only supports k=16" +#endif + + uint32_t tp[PARAM_N]; + + /* The reference implementation calls ChaCha20 here. */ + RAND_bytes((uint8_t *) tp, sizeof(tp)); + + size_t i; + for (i = 0; i < PARAM_N; i++) { + const uint32_t t = tp[i]; + + size_t j; + uint32_t d = 0; + for (j = 0; j < 8; j++) { + d += (t >> j) & 0x01010101; + } + + const uint32_t a = ((d >> 8) & 0xff) + (d & 0xff); + const uint32_t b = (d >> 24) + ((d >> 16) & 0xff); + r->coeffs[i] = a + PARAM_Q - b; + } +} + +void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b) { + size_t i; + for (i = 0; i < PARAM_N; i++) { + uint16_t t = newhope_montgomery_reduce(3186 * b->coeffs[i]); + /* t is now in Montgomery domain */ + r->coeffs[i] = newhope_montgomery_reduce(a->coeffs[i] * t); + /* r->coeffs[i] is back in normal domain */ + } +} + +void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b) { + size_t i; + for (i = 0; i < PARAM_N; i++) { + r->coeffs[i] = newhope_barrett_reduce(a->coeffs[i] + b->coeffs[i]); + } +} + +void NEWHOPE_POLY_noise_ntt(NEWHOPE_POLY* r) { + NEWHOPE_POLY_noise(r); + /* Forward NTT transformation. Because we're operating on a noise polynomial, + * we can regard the bits as already reversed and skip the bit-reversal + * step: + * + * newhope_bitrev_vector(r->coeffs); */ + newhope_mul_coefficients(r->coeffs, newhope_psis_bitrev_montgomery); + newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_montgomery); +} + +void newhope_poly_invntt(NEWHOPE_POLY* r) { + newhope_bitrev_vector(r->coeffs); + newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_inv_montgomery); + newhope_mul_coefficients(r->coeffs, newhope_psis_inv_montgomery); +} diff --git a/external/boringssl/crypto/newhope/precomp.c b/external/boringssl/crypto/newhope/precomp.c new file mode 100644 index 0000000000..d0c478eefe --- /dev/null +++ b/external/boringssl/crypto/newhope/precomp.c @@ -0,0 +1,306 @@ +/* Copyright (c) 2016, 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 "internal.h" + + +uint16_t newhope_omegas_montgomery[PARAM_N / 2] = { + 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, + 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118, + 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973, + 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930, + 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643, + 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605, + 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080, + 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142, + 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968, + 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821, + 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874, + 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281, + 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453, + 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030, + 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939, + 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706, + 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634, + 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459, + 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065, + 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, + 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948, + 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992, + 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106, + 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969, + 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553, + 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088, + 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479, + 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961, + 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744, + 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374, + 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011, + 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791, + 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755, + 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637, + 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207, + 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952, + 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302, + 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045, + 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, + 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, + 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618, + 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730, + 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686, + 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863, + 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852, + 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364, + 3271, 4057, 4414, 9442, 7917, 2174}; + +uint16_t newhope_omegas_inv_montgomery[PARAM_N / 2] = { + 4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278, + 9945, 3514, 11248, 11271, 5925, 147, 8500, 7840, 6833, 5537, 4749, + 4467, 7500, 11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, 9090, + 12233, 5529, 5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427, + 7341, 6152, 10561, 400, 8410, 1922, 2033, 8291, 1359, 6854, 11035, + 973, 8579, 6093, 6950, 5446, 11821, 8301, 11907, 316, 52, 3174, + 10966, 9523, 6055, 8953, 11612, 6415, 2505, 5906, 10710, 11858, 8332, + 9450, 10162, 151, 3482, 787, 5468, 1010, 4169, 9162, 5241, 9369, + 7509, 8844, 7232, 4698, 192, 1321, 10240, 4912, 885, 6281, 10333, + 7280, 8757, 11286, 58, 12048, 12147, 11184, 8812, 6608, 2844, 3438, + 4212, 11314, 8687, 6068, 421, 8209, 3600, 3263, 7665, 6077, 7507, + 5886, 3029, 6695, 4213, 504, 11684, 2302, 1962, 1594, 6328, 7183, + 168, 2692, 8960, 4298, 5184, 11089, 6122, 9734, 10929, 3956, 5297, + 6170, 3762, 9370, 4016, 4077, 6523, 652, 11994, 6099, 1146, 11341, + 11964, 10885, 6299, 1159, 8240, 8561, 11177, 2078, 10331, 4322, 11367, + 441, 4079, 11231, 3150, 1319, 8243, 709, 8049, 8719, 11454, 6224, + 3054, 6803, 3123, 10542, 4433, 6370, 7032, 3834, 8633, 12225, 9830, + 683, 1566, 5782, 9786, 9341, 12115, 723, 3009, 1693, 5735, 2655, + 2738, 6421, 11942, 2925, 1975, 8532, 3315, 11863, 4754, 1858, 1583, + 6347, 2500, 10800, 6374, 1483, 12240, 1263, 1815, 5383, 10777, 350, + 6920, 10232, 4493, 9087, 8855, 8760, 9381, 218, 9928, 10446, 9259, + 4115, 6147, 9842, 8326, 576, 10335, 10238, 10484, 9407, 6381, 11836, + 8517, 418, 6860, 7515, 1293, 7552, 2767, 156, 8298, 8320, 10008, + 5876, 5333, 10258, 10115, 4372, 2847, 7875, 8232, 9018, 8925, 1689, + 8236, 2645, 5042, 9984, 7094, 9509, 1484, 7394, 3, 4437, 160, + 3149, 113, 7370, 10123, 3915, 6998, 2704, 8653, 4938, 1426, 7635, + 10512, 1663, 6957, 3510, 2370, 2865, 3978, 9320, 3247, 9603, 6882, + 3186, 10659, 10163, 1153, 9405, 8241, 10040, 2178, 1544, 5559, 420, + 8304, 4905, 476, 3531, 5191, 9153, 2399, 8889, 3000, 671, 243, + 3016, 3763, 10849, 12262, 9223, 10657, 7205, 11272, 7404, 7575, 8146, + 10752, 242, 2678, 3704, 11744, 5019, 3833, 3778, 11899, 773, 5101, + 11222, 9888, 442, 2912, 5698, 11935, 4861, 7277, 9808, 11244, 2859, + 3780, 11414, 4976, 10682, 7201, 8005, 11287, 5011, 6267, 2987, 2437, + 3646, 2566, 10102, 9867, 6250, 5444, 2381, 11796, 8193, 4337, 11854, + 1912, 1378, 404, 7644, 1065, 2143, 11121, 5277, 3248, 11082, 2548, + 8058, 8907, 11934, 1759, 8582, 3694, 7110, 12144, 6747, 8652, 3459, + 2731, 8357, 6378, 7399, 10861, 1696, 9863, 334, 7657, 6534, 11029, + 4388, 11560, 3241, 10276, 9000, 9408, 3284, 10200, 7197, 6498, 544, + 2468, 339, 11267, 9, 2842, 480, 5331, 7300, 1673, 4278, 4177, + 8705, 9764, 1381, 7837, 2396, 8340, 8993, 4354, 130, 6915, 2837, + 11462, 5767, 953, 8541, 9813, 118, 7222, 2197, 3006, 9545, 563, + 9314, 2625, 11340, 4821, 2639, 7266, 5828, 6561, 7698, 3328, 6512, + 1351, 7311, 6553, 8155, 1305, 722, 5146, 4043, 12288, 10810, 2545, + 3621, 8747, 8785, 1646, 1212, 5860, 3195, 7203, 10963, 3201, 3014, + 955, 11499, 9970, 11119, 3135, 3712, 7443, 9542, 7484, 8736, 9995, + 11227, 1635, 9521, 1177, 8034, 140, 10436, 11563, 7678, 4320, 11289, + 9198, 12208, 2963, 7393, 2366, 9238}; + +uint16_t newhope_psis_bitrev_montgomery[PARAM_N] = { + 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, + 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118, + 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973, + 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930, + 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643, + 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605, + 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080, + 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142, + 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968, + 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821, + 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874, + 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281, + 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453, + 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030, + 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939, + 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706, + 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634, + 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459, + 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065, + 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, + 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948, + 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992, + 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106, + 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969, + 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553, + 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088, + 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479, + 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961, + 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744, + 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374, + 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011, + 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791, + 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755, + 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637, + 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207, + 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952, + 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302, + 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045, + 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, + 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, + 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618, + 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730, + 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686, + 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863, + 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852, + 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364, + 3271, 4057, 4414, 9442, 7917, 2174, 3947, 11951, 2455, 6599, 10545, + 10975, 3654, 2894, 7681, 7126, 7287, 12269, 4119, 3343, 2151, 1522, + 7174, 7350, 11041, 2442, 2148, 5959, 6492, 8330, 8945, 5598, 3624, + 10397, 1325, 6565, 1945, 11260, 10077, 2674, 3338, 3276, 11034, 506, + 6505, 1392, 5478, 8778, 1178, 2776, 3408, 10347, 11124, 2575, 9489, + 12096, 6092, 10058, 4167, 6085, 923, 11251, 11912, 4578, 10669, 11914, + 425, 10453, 392, 10104, 8464, 4235, 8761, 7376, 2291, 3375, 7954, + 8896, 6617, 7790, 1737, 11667, 3982, 9342, 6680, 636, 6825, 7383, + 512, 4670, 2900, 12050, 7735, 994, 1687, 11883, 7021, 146, 10485, + 1403, 5189, 6094, 2483, 2054, 3042, 10945, 3981, 10821, 11826, 8882, + 8151, 180, 9600, 7684, 5219, 10880, 6780, 204, 11232, 2600, 7584, + 3121, 3017, 11053, 7814, 7043, 4251, 4739, 11063, 6771, 7073, 9261, + 2360, 11925, 1928, 11825, 8024, 3678, 3205, 3359, 11197, 5209, 8581, + 3238, 8840, 1136, 9363, 1826, 3171, 4489, 7885, 346, 2068, 1389, + 8257, 3163, 4840, 6127, 8062, 8921, 612, 4238, 10763, 8067, 125, + 11749, 10125, 5416, 2110, 716, 9839, 10584, 11475, 11873, 3448, 343, + 1908, 4538, 10423, 7078, 4727, 1208, 11572, 3589, 2982, 1373, 1721, + 10753, 4103, 2429, 4209, 5412, 5993, 9011, 438, 3515, 7228, 1218, + 8347, 5232, 8682, 1327, 7508, 4924, 448, 1014, 10029, 12221, 4566, + 5836, 12229, 2717, 1535, 3200, 5588, 5845, 412, 5102, 7326, 3744, + 3056, 2528, 7406, 8314, 9202, 6454, 6613, 1417, 10032, 7784, 1518, + 3765, 4176, 5063, 9828, 2275, 6636, 4267, 6463, 2065, 7725, 3495, + 8328, 8755, 8144, 10533, 5966, 12077, 9175, 9520, 5596, 6302, 8400, + 579, 6781, 11014, 5734, 11113, 11164, 4860, 1131, 10844, 9068, 8016, + 9694, 3837, 567, 9348, 7000, 6627, 7699, 5082, 682, 11309, 5207, + 4050, 7087, 844, 7434, 3769, 293, 9057, 6940, 9344, 10883, 2633, + 8190, 3944, 5530, 5604, 3480, 2171, 9282, 11024, 2213, 8136, 3805, + 767, 12239, 216, 11520, 6763, 10353, 7, 8566, 845, 7235, 3154, + 4360, 3285, 10268, 2832, 3572, 1282, 7559, 3229, 8360, 10583, 6105, + 3120, 6643, 6203, 8536, 8348, 6919, 3536, 9199, 10891, 11463, 5043, + 1658, 5618, 8787, 5789, 4719, 751, 11379, 6389, 10783, 3065, 7806, + 6586, 2622, 5386, 510, 7628, 6921, 578, 10345, 11839, 8929, 4684, + 12226, 7154, 9916, 7302, 8481, 3670, 11066, 2334, 1590, 7878, 10734, + 1802, 1891, 5103, 6151, 8820, 3418, 7846, 9951, 4693, 417, 9996, + 9652, 4510, 2946, 5461, 365, 881, 1927, 1015, 11675, 11009, 1371, + 12265, 2485, 11385, 5039, 6742, 8449, 1842, 12217, 8176, 9577, 4834, + 7937, 9461, 2643, 11194, 3045, 6508, 4094, 3451, 7911, 11048, 5406, + 4665, 3020, 6616, 11345, 7519, 3669, 5287, 1790, 7014, 5410, 11038, + 11249, 2035, 6125, 10407, 4565, 7315, 5078, 10506, 2840, 2478, 9270, + 4194, 9195, 4518, 7469, 1160, 6878, 2730, 10421, 10036, 1734, 3815, + 10939, 5832, 10595, 10759, 4423, 8420, 9617, 7119, 11010, 11424, 9173, + 189, 10080, 10526, 3466, 10588, 7592, 3578, 11511, 7785, 9663, 530, + 12150, 8957, 2532, 3317, 9349, 10243, 1481, 9332, 3454, 3758, 7899, + 4218, 2593, 11410, 2276, 982, 6513, 1849, 8494, 9021, 4523, 7988, + 8, 457, 648, 150, 8000, 2307, 2301, 874, 5650, 170, 9462, + 2873, 9855, 11498, 2535, 11169, 5808, 12268, 9687, 1901, 7171, 11787, + 3846, 1573, 6063, 3793, 466, 11259, 10608, 3821, 6320, 4649, 6263, + 2929}; + +uint16_t newhope_psis_inv_montgomery[PARAM_N] = { + 256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000, + 2327, 2088, 5565, 795, 10647, 1521, 5484, 2539, 7385, 1055, 7173, + 8047, 11683, 1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, 10525, + 12037, 12253, 3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207, + 5582, 2553, 7387, 6322, 9681, 1383, 10731, 1533, 219, 5298, 4268, + 7632, 6357, 9686, 8406, 4712, 9451, 10128, 4958, 5975, 11387, 8649, + 11769, 6948, 11526, 12180, 1740, 10782, 6807, 2728, 7412, 4570, 4164, + 4106, 11120, 12122, 8754, 11784, 3439, 5758, 11356, 6889, 9762, 11928, + 1704, 1999, 10819, 12079, 12259, 7018, 11536, 1648, 1991, 2040, 2047, + 2048, 10826, 12080, 8748, 8272, 8204, 1172, 1923, 7297, 2798, 7422, + 6327, 4415, 7653, 6360, 11442, 12168, 7005, 8023, 9924, 8440, 8228, + 2931, 7441, 1063, 3663, 5790, 9605, 10150, 1450, 8985, 11817, 10466, + 10273, 12001, 3470, 7518, 1074, 1909, 7295, 9820, 4914, 702, 5367, + 7789, 8135, 9940, 1420, 3714, 11064, 12114, 12264, 1752, 5517, 9566, + 11900, 1700, 3754, 5803, 829, 1874, 7290, 2797, 10933, 5073, 7747, + 8129, 6428, 6185, 11417, 1631, 233, 5300, 9535, 10140, 11982, 8734, + 8270, 2937, 10953, 8587, 8249, 2934, 9197, 4825, 5956, 4362, 9401, + 1343, 3703, 529, 10609, 12049, 6988, 6265, 895, 3639, 4031, 4087, + 4095, 585, 10617, 8539, 4731, 4187, 9376, 3095, 9220, 10095, 10220, + 1460, 10742, 12068, 1724, 5513, 11321, 6884, 2739, 5658, 6075, 4379, + 11159, 10372, 8504, 4726, 9453, 3106, 7466, 11600, 10435, 8513, 9994, + 8450, 9985, 3182, 10988, 8592, 2983, 9204, 4826, 2445, 5616, 6069, + 867, 3635, 5786, 11360, 5134, 2489, 10889, 12089, 1727, 7269, 2794, + 9177, 1311, 5454, 9557, 6632, 2703, 9164, 10087, 1441, 3717, 531, + 3587, 2268, 324, 5313, 759, 1864, 5533, 2546, 7386, 9833, 8427, + 4715, 11207, 1601, 7251, 4547, 11183, 12131, 1733, 10781, 10318, 1474, + 10744, 5046, 4232, 11138, 10369, 6748, 964, 7160, 4534, 7670, 8118, + 8182, 4680, 11202, 6867, 981, 8918, 1274, 182, 26, 7026, 8026, + 11680, 12202, 10521, 1503, 7237, 4545, 5916, 9623, 8397, 11733, 10454, + 3249, 9242, 6587, 941, 1890, 270, 10572, 6777, 9746, 6659, 6218, + 6155, 6146, 878, 1881, 7291, 11575, 12187, 1741, 7271, 8061, 11685, + 6936, 4502, 9421, 4857, 4205, 7623, 1089, 10689, 1527, 8996, 10063, + 11971, 10488, 6765, 2722, 3900, 9335, 11867, 6962, 11528, 5158, 4248, + 4118, 5855, 2592, 5637, 6072, 2623, 7397, 8079, 9932, 4930, 5971, + 853, 3633, 519, 8852, 11798, 3441, 11025, 1575, 225, 8810, 11792, + 12218, 3501, 9278, 3081, 9218, 4828, 7712, 8124, 11694, 12204, 3499, + 4011, 573, 3593, 5780, 7848, 9899, 10192, 1456, 208, 7052, 2763, + 7417, 11593, 10434, 12024, 8740, 11782, 10461, 3250, 5731, 7841, 9898, + 1414, 202, 3540, 7528, 2831, 2160, 10842, 5060, 4234, 4116, 588, + 84, 12, 7024, 2759, 9172, 6577, 11473, 1639, 9012, 3043, 7457, + 6332, 11438, 1634, 1989, 9062, 11828, 8712, 11778, 12216, 10523, 6770, + 9745, 10170, 4964, 9487, 6622, 946, 8913, 6540, 6201, 4397, 9406, + 8366, 9973, 8447, 8229, 11709, 8695, 10020, 3187, 5722, 2573, 10901, + 6824, 4486, 4152, 9371, 8361, 2950, 2177, 311, 1800, 9035, 8313, + 11721, 3430, 490, 70, 10, 1757, 251, 3547, 7529, 11609, 3414, + 7510, 4584, 4166, 9373, 1339, 5458, 7802, 11648, 1664, 7260, 9815, + 10180, 6721, 9738, 10169, 8475, 8233, 9954, 1422, 8981, 1283, 5450, + 11312, 1616, 3742, 11068, 10359, 4991, 713, 3613, 9294, 8350, 4704, + 672, 96, 7036, 9783, 11931, 3460, 5761, 823, 10651, 12055, 10500, + 1500, 5481, 783, 3623, 11051, 8601, 8251, 8201, 11705, 10450, 5004, + 4226, 7626, 2845, 2162, 3820, 7568, 9859, 3164, 452, 10598, 1514, + 5483, 6050, 6131, 4387, 7649, 8115, 6426, 918, 8909, 8295, 1185, + 5436, 11310, 8638, 1234, 5443, 11311, 5127, 2488, 2111, 10835, 5059, + 7745, 2862, 3920, 560, 80, 1767, 2008, 3798, 11076, 6849, 2734, + 10924, 12094, 8750, 1250, 10712, 6797, 971, 7161, 1023, 8924, 4786, + 7706, 4612, 4170, 7618, 6355, 4419, 5898, 11376, 10403, 10264, 6733, + 4473, 639, 5358, 2521, 9138, 3061, 5704, 4326, 618, 5355, 765, + 5376, 768, 7132, 4530, 9425, 3102, 9221, 6584, 11474, 10417, 10266, + 12000, 6981, 6264, 4406, 2385, 7363, 4563, 4163, 7617, 9866, 3165, + 9230, 11852, 10471, 5007, 5982, 11388, 5138, 734, 3616, 11050, 12112, + 6997, 11533, 12181, 10518, 12036, 3475, 2252, 7344, 9827, 4915, 9480, + 6621, 4457, 7659, 9872, 6677, 4465, 4149, 7615, 4599, 657, 3605, + 515, 10607, 6782, 4480, 640, 1847, 3775, 5806, 2585, 5636, 9583, + 1369, 10729, 8555, 10000, 11962, 5220, 7768, 8132, 8184, 9947, 1421, + 203, 29, 8782, 11788, 1684, 10774, 10317, 4985, 9490, 8378, 4708, + 11206, 5112, 5997, 7879, 11659, 12199, 8765, 10030, 4944, 5973, 6120, + 6141, 6144, 7900, 11662, 1666, 238, 34, 3516, 5769, 9602, 8394, + 9977, 6692, 956, 10670, 6791, 9748, 11926, 8726, 11780, 5194, 742, + 106, 8793, 10034, 3189, 10989, 5081, 4237, 5872, 4350, 2377, 10873, + 6820, 6241, 11425, 10410, 10265, 3222, 5727, 9596, 4882, 2453, 2106, + 3812, 11078, 12116, 5242, 4260, 11142, 8614, 11764, 12214, 5256, 4262, + 4120, 11122, 5100, 11262, 5120, 2487, 5622, 9581, 8391, 8221, 2930, + 10952, 12098, 6995, 6266, 9673, 4893, 699, 3611, 4027, 5842, 11368, + 1624, 232, 8811, 8281, 1183, 169, 8802, 3013, 2186, 5579, 797, + 3625, 4029, 11109, 1587, 7249, 11569, 8675, 6506, 2685, 10917, 12093, + 12261, 12285, 1755, 7273, 1039, 1904, 272, 3550, 9285, 3082, 5707, + 6082, 4380, 7648, 11626, 5172, 4250, 9385, 8363, 8217, 4685, 5936, + 848, 8899, 6538, 934, 1889, 3781, 9318, 10109, 10222, 6727, 961, + 5404, 772, 5377, 9546, 8386, 1198, 8949, 3034, 2189, 7335, 4559, + 5918, 2601, 10905, 5069, 9502, 3113, 7467, 8089, 11689, 5181, 9518, + 8382, 2953, 3933, 4073, 4093, 7607, 8109, 2914, 5683, 4323, 11151, + 1593, 10761, 6804, 972, 3650, 2277, 5592, 4310, 7638, 9869, 4921, + 703, 1856, 9043, 4803, 9464, 1352, 8971, 11815, 5199, 7765, 6376, + 4422, 7654, 2849, 407, 8836, 6529, 7955, 2892, 9191, 1313, 10721, + 12065, 12257, 1751, 9028, 8312, 2943, 2176, 3822, 546, 78, 8789, + 11789, 10462, 12028, 6985, 4509, 9422, 1346, 5459, 4291, 613, 10621, + 6784, 9747, 3148, 7472, 2823, 5670, 810, 7138, 8042, 4660, 7688, + 6365, 6176, 6149, 2634, 5643, 9584, 10147, 11983, 5223, 9524, 11894, + 10477, 8519, 1217, 3685, 2282, 326, 10580, 3267, 7489, 4581, 2410, + 5611, 11335, 6886, 8006, 8166, 11700, 3427, 11023, 8597, 10006, 3185, + 455, 65, 5276, 7776, 4622, 5927, 7869, 9902, 11948, 5218, 2501, + 5624, 2559, 10899, 1557, 1978, 10816, 10323, 8497, 4725, 675, 1852, + 10798, 12076, 10503, 3256, 9243, 3076, 2195, 10847, 12083, 10504, 12034, + 10497}; diff --git a/external/boringssl/crypto/newhope/reduce.c b/external/boringssl/crypto/newhope/reduce.c new file mode 100644 index 0000000000..e7f1364947 --- /dev/null +++ b/external/boringssl/crypto/newhope/reduce.c @@ -0,0 +1,42 @@ +/* Copyright (c) 2016, 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 "internal.h" + + +/* Incomplete-reduction routines; for details on allowed input ranges + * and produced output ranges, see the description in the paper: + * https://cryptojedi.org/papers/#newhope */ + +static const uint32_t kQInv = 12287; /* -inverse_mod(p,2^18) */ +static const uint32_t kRLog = 18; + +uint16_t newhope_montgomery_reduce(uint32_t a) { + uint32_t u; + + u = (a * kQInv); + u &= ((1 << kRLog) - 1); + u *= PARAM_Q; + a = a + u; + return a >> 18; +} + +uint16_t newhope_barrett_reduce(uint16_t a) { + uint32_t u; + + u = ((uint32_t)a * 5) >> 16; + u *= PARAM_Q; + a -= u; + return a; +} diff --git a/external/boringssl/crypto/obj/CMakeLists.txt b/external/boringssl/crypto/obj/CMakeLists.txt new file mode 100644 index 0000000000..46b7918ddb --- /dev/null +++ b/external/boringssl/crypto/obj/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + obj + + OBJECT + + obj.c + obj_xref.c +) + +if(ENABLE_TESTS) +add_executable( + obj_test + + obj_test.cc + + $ +) + +target_link_libraries(obj_test crypto) +add_dependencies(all_tests obj_test) +endif() \ No newline at end of file diff --git a/external/boringssl/crypto/obj/README b/external/boringssl/crypto/obj/README new file mode 100644 index 0000000000..6199fb4b77 --- /dev/null +++ b/external/boringssl/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/nid.h + perl obj_dat.pl ../../include/openssl/nid.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 nid.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. nid.h is the header which defines macros for all the +built-in OIDs in C. + +nid.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 | + nid.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/external/boringssl/crypto/obj/obj.c b/external/boringssl/crypto/obj/obj.c new file mode 100644 index 0000000000..16d964c546 --- /dev/null +++ b/external/boringssl/crypto/obj/obj.c @@ -0,0 +1,664 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "obj_dat.h" +#include "../internal.h" + + +static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT; +/* These globals are protected by |global_added_lock|. */ +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 struct CRYPTO_STATIC_MUTEX global_next_nid_lock = + CRYPTO_STATIC_MUTEX_INIT; +static unsigned global_next_nid = NUM_NID; + +static int obj_next_nid(void) { + int ret; + + CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock); + ret = global_next_nid++; + CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock); + + 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, 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 == NULL) { + 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, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ln); + OPENSSL_free(sn); + 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); +} + +/* obj_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) { + unsigned nid = *((const unsigned*) element); + const ASN1_OBJECT *a = key; + const ASN1_OBJECT *b = &kObjects[nid]; + + if (a->length < b->length) { + return -1; + } else if (a->length > b->length) { + return 1; + } + 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_STATIC_MUTEX_lock_read(&global_added_lock); + if (global_added_by_data != NULL) { + ASN1_OBJECT *match; + + match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj); + if (match != NULL) { + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + return match->nid; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + + 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_STATIC_MUTEX_lock_read(&global_added_lock); + 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_STATIC_MUTEX_unlock_read(&global_added_lock); + return match->nid; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + + 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_STATIC_MUTEX_lock_read(&global_added_lock); + 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_STATIC_MUTEX_unlock_read(&global_added_lock); + return match->nid; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + + 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_STATIC_MUTEX_lock_read(&global_added_lock); + 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_STATIC_MUTEX_unlock_read(&global_added_lock); + return match; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + +err: + OPENSSL_PUT_ERROR(OBJ, 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, 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; + } + } + + BN_free(bl); + return n; + +err: + 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_STATIC_MUTEX_lock_write(&global_added_lock); + 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_STATIC_MUTEX_unlock_write(&global_added_lock); + + 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, 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: + ASN1_OBJECT_free(op); + OPENSSL_free(buf); + + return ret; +} diff --git a/external/boringssl/crypto/obj/obj_dat.h.REMOVED.git-id b/external/boringssl/crypto/obj/obj_dat.h.REMOVED.git-id new file mode 100644 index 0000000000..f19e464893 --- /dev/null +++ b/external/boringssl/crypto/obj/obj_dat.h.REMOVED.git-id @@ -0,0 +1 @@ +1d779de67cfa59075f036966689c181d7e048889 \ No newline at end of file diff --git a/external/boringssl/crypto/obj/obj_dat.pl b/external/boringssl/crypto/obj/obj_dat.pl new file mode 100644 index 0000000000..036ded5432 --- /dev/null +++ b/external/boringssl/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/nid.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 () + { + 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{$_}}) && $objd{$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/nid.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/external/boringssl/crypto/obj/obj_mac.num b/external/boringssl/crypto/obj/obj_mac.num new file mode 100644 index 0000000000..3a7844cd7f --- /dev/null +++ b/external/boringssl/crypto/obj/obj_mac.num @@ -0,0 +1,949 @@ +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 +X25519 948 +cecpq1 949 diff --git a/external/boringssl/crypto/obj/obj_test.cc b/external/boringssl/crypto/obj/obj_test.cc new file mode 100644 index 0000000000..2948941af4 --- /dev/null +++ b/external/boringssl/crypto/obj/obj_test.cc @@ -0,0 +1,106 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include + + +static bool TestBasic() { + static const int kNID = NID_sha256WithRSAEncryption; + static const char kShortName[] = "RSA-SHA256"; + static const char kLongName[] = "sha256WithRSAEncryption"; + static const char kText[] = "1.2.840.113549.1.1.11"; + static const uint8_t kDER[] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + }; + + CBS cbs; + CBS_init(&cbs, kDER, sizeof(kDER)); + if (OBJ_cbs2nid(&cbs) != kNID || + OBJ_sn2nid(kShortName) != kNID || + OBJ_ln2nid(kLongName) != kNID || + OBJ_txt2nid(kShortName) != kNID || + OBJ_txt2nid(kLongName) != kNID || + OBJ_txt2nid(kText) != kNID) { + return false; + } + + if (strcmp(kShortName, OBJ_nid2sn(kNID)) != 0 || + strcmp(kLongName, OBJ_nid2ln(kNID)) != 0) { + return false; + } + + if (OBJ_sn2nid("this is not an OID") != NID_undef || + OBJ_ln2nid("this is not an OID") != NID_undef || + OBJ_txt2nid("this is not an OID") != NID_undef) { + return false; + } + + CBS_init(&cbs, NULL, 0); + if (OBJ_cbs2nid(&cbs) != NID_undef) { + return false; + } + + // 1.2.840.113554.4.1.72585.2 (https://davidben.net/oid). + static const uint8_t kUnknownDER[] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, + }; + CBS_init(&cbs, kUnknownDER, sizeof(kUnknownDER)); + if (OBJ_cbs2nid(&cbs) != NID_undef) { + return false; + } + + return true; +} + +static bool TestSignatureAlgorithms() { + int digest_nid, pkey_nid; + if (!OBJ_find_sigid_algs(NID_sha256WithRSAEncryption, &digest_nid, + &pkey_nid) || + digest_nid != NID_sha256 || pkey_nid != NID_rsaEncryption) { + return false; + } + + if (OBJ_find_sigid_algs(NID_sha256, &digest_nid, &pkey_nid)) { + return false; + } + + int sign_nid; + if (!OBJ_find_sigid_by_algs(&sign_nid, NID_sha256, NID_rsaEncryption) || + sign_nid != NID_sha256WithRSAEncryption) { + return false; + } + + if (OBJ_find_sigid_by_algs(&sign_nid, NID_dsa, NID_rsaEncryption)) { + return false; + } + + return true; +} + +int main() { + CRYPTO_library_init(); + + if (!TestBasic() || + !TestSignatureAlgorithms()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/obj/obj_xref.c b/external/boringssl/crypto/obj/obj_xref.c new file mode 100644 index 0000000000..70babea84b --- /dev/null +++ b/external/boringssl/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 + +#include + +#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/external/boringssl/crypto/obj/obj_xref.h b/external/boringssl/crypto/obj/obj_xref.h new file mode 100644 index 0000000000..b2082f55bd --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/obj/obj_xref.pl b/external/boringssl/crypto/obj/obj_xref.pl new file mode 100644 index 0000000000..51dd68f450 --- /dev/null +++ b/external/boringssl/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 () + { + 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 () + { + 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 < 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 <) + { + 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 () + { + 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/nid.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.] + */ + +#ifndef OPENSSL_HEADER_NID_H +#define OPENSSL_HEADER_NID_H + + +/* The nid library provides numbered values for ASN.1 object identifiers and + * other symbols. These values are used by other libraries to identify + * cryptographic primitives. + * + * A separate objects library, obj.h, provides functions for converting between + * nids and object identifiers. However it depends on large internal tables with + * the encodings of every nid defind. Consumers concerned with binary size + * should instead embed the encodings of the few consumed OIDs and compare + * against those. + * + * These values should not be used outside of a single process; they are not + * stable identifiers. */ + + +#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," \"",$sn{$Cname},"\"\n" if $sn{$Cname} ne ""; + print OUT "#define LN_",$Cname," \"",$ln{$Cname},"\"\n" if $ln{$Cname} ne ""; + print OUT "#define NID_",$Cname," ",$nid{$Cname},"\n" if $nid{$Cname} ne ""; + print OUT "#define OBJ_",$Cname," ",$obj{$Cname},"\n" if $obj{$Cname} ne ""; + print OUT "\n"; + } + +print OUT "\n#endif /* OPENSSL_HEADER_NID_H */\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/external/boringssl/crypto/obj/objects.txt b/external/boringssl/crypto/obj/objects.txt new file mode 100644 index 0000000000..75f2cbf9f8 --- /dev/null +++ b/external/boringssl/crypto/obj/objects.txt @@ -0,0 +1,1338 @@ +# 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 Distribution 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 + +# RFC 3274 +!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 + +# NID for X25519 (no corresponding OID). + : X25519 + +# NID for CECPQ1 (no corresponding OID) + : cecpq1 diff --git a/external/boringssl/crypto/pem/CMakeLists.txt b/external/boringssl/crypto/pem/CMakeLists.txt new file mode 100644 index 0000000000..30dd7c92a7 --- /dev/null +++ b/external/boringssl/crypto/pem/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories(../../include) + +add_library( + pem + + OBJECT + + pem_all.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/external/boringssl/crypto/pem/pem_all.c b/external/boringssl/crypto/pem/pem_all.c new file mode 100644 index 0000000000..e94ff2655f --- /dev/null +++ b/external/boringssl/crypto/pem/pem_all.c @@ -0,0 +1,262 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +/* + * #include + */ +#include +#include + +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 */ +} + +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) + + IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) diff --git a/external/boringssl/crypto/pem/pem_info.c b/external/boringssl/crypto/pem/pem_info.c new file mode 100644 index 0000000000..57c87d4fc2 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_info.c @@ -0,0 +1,381 @@ +/* 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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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, 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, 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, ERR_R_ASN1_LIB); + goto err; + } + } else if (d2i(pp, &p, len) == NULL) { + OPENSSL_PUT_ERROR(PEM, 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; 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_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_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_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/external/boringssl/crypto/pem/pem_lib.c b/external/boringssl/crypto/pem/pem_lib.c new file mode 100644 index 0000000000..e53abf8611 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_lib.c @@ -0,0 +1,778 @@ +/* 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); + +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, 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)) { + return !strcmp(nm, PEM_STRING_PKCS8) || + !strcmp(nm, PEM_STRING_PKCS8INF) || + !strcmp(nm, PEM_STRING_RSA) || + !strcmp(nm, PEM_STRING_EC) || + !strcmp(nm, PEM_STRING_DSA); + } + + /* 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, 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 || EVP_CIPHER_iv_length(enc) == 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + } + + if ((dsize = i2d(x, NULL)) < 0) { + OPENSSL_PUT_ERROR(PEM, 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, 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) + callback = PEM_def_callback; + klen = (*callback) (buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, 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; + else + i += j; + EVP_CIPHER_CTX_cleanup(&ctx); + if (ret == 0) + goto err; + } 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) + callback = PEM_def_callback; + klen = callback(buf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, 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_R_BAD_DECRYPT); + return (0); + } + j += i; + *plen = j; + return (1); +} + +static const EVP_CIPHER *cipher_by_name(const char *name) +{ + /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. */ + if (0 == strcmp(name, SN_rc4)) { + return EVP_rc4(); + } else if (0 == strcmp(name, SN_des_cbc)) { + return EVP_des_cbc(); + } else if (0 == strcmp(name, SN_des_ede3_cbc)) { + return EVP_des_ede3_cbc(); + } else if (0 == strcmp(name, SN_aes_128_cbc)) { + return EVP_aes_128_cbc(); + } else if (0 == strcmp(name, SN_aes_192_cbc)) { + return EVP_aes_192_cbc(); + } else if (0 == strcmp(name, SN_aes_256_cbc)) { + 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_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_R_NOT_ENCRYPTED); + return (0); + } + for (; (*header != '\n') && (*header != '\0'); header++) ; + if (*header == '\0') { + OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER); + return (0); + } + header++; + if (strncmp(header, "DEK-Info: ", 10) != 0) { + OPENSSL_PUT_ERROR(PEM, 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_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, 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, 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, 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, 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, ERR_R_MALLOC_FAILURE); + return (0); + } + + buf[254] = '\0'; + for (;;) { + i = BIO_gets(bp, buf, 254); + + if (i <= 0) { + OPENSSL_PUT_ERROR(PEM, 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, 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, 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, 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, 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, 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_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_R_BAD_BASE64_DECODE); + goto err; + } + i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k); + if (i < 0) { + OPENSSL_PUT_ERROR(PEM, 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); +} + +int PEM_def_callback(char *buf, int size, int rwflag, void *userdata) +{ + if (!buf || !userdata) { + return 0; + } + size_t len = strlen((char *)userdata); + if (len >= (size_t)size) { + return 0; + } + strcpy(buf, (char *)userdata); + return len; +} diff --git a/external/boringssl/crypto/pem/pem_oth.c b/external/boringssl/crypto/pem/pem_oth.c new file mode 100644 index 0000000000..8530c56756 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_oth.c @@ -0,0 +1,88 @@ +/* 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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Handle 'other' PEMs: not private keys */ + +void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, + pem_password_cb *cb, void *u) +{ + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + char *ret = NULL; + + if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u)) + return NULL; + p = data; + ret = d2i(x, &p, len); + if (ret == NULL) + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + OPENSSL_free(data); + return ret; +} diff --git a/external/boringssl/crypto/pem/pem_pk8.c b/external/boringssl/crypto/pem/pem_pk8.c new file mode 100644 index 0000000000..550661d642 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_pk8.c @@ -0,0 +1,257 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u); +static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u); + +/* + * These functions write a private key in PKCS#8 format: it is a "drop in" + * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc' + * is NULL then it uses the unencrypted private key form. The 'nid' versions + * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0. + */ + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); +} + +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, PEM_R_ERROR_CONVERTING_PRIVATE_KEY); + return 0; + } + if (enc || (nid != -1)) { + if (!kstr) { + klen = 0; + if (!cb) + cb = PEM_def_callback; + klen = cb(buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, 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) + cb = PEM_def_callback; + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, 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, 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, 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/external/boringssl/crypto/pem/pem_pkey.c b/external/boringssl/crypto/pem/pem_pkey.c new file mode 100644 index 0000000000..058c031125 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_pkey.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.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + 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) + cb = PEM_def_callback; + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, 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 (strcmp(nm, PEM_STRING_RSA) == 0) { + /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the + * standalone format. This and the cases below probably should not + * accept PKCS#8. */ + ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); + } else if (strcmp(nm, PEM_STRING_EC) == 0) { + ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); + } else if (strcmp(nm, PEM_STRING_DSA) == 0) { + ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len); + } + p8err: + if (ret == NULL) + OPENSSL_PUT_ERROR(PEM, 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) +{ + return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u); +} + +#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, 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, 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; + + ret = d2i_DHparams(x, &p, len); + + if (ret == NULL) + OPENSSL_PUT_ERROR(PEM, 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, 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/external/boringssl/crypto/pem/pem_x509.c b/external/boringssl/crypto/pem/pem_x509.c new file mode 100644 index 0000000000..97f814dba0 --- /dev/null +++ b/external/boringssl/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 + +#include +#include +#include +#include + +IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509) diff --git a/external/boringssl/crypto/pem/pem_xaux.c b/external/boringssl/crypto/pem/pem_xaux.c new file mode 100644 index 0000000000..386dd60d76 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_xaux.c @@ -0,0 +1,67 @@ +/* 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 + +#include +#include +#include +#include + +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/external/boringssl/crypto/perlasm/arm-xlate.pl b/external/boringssl/crypto/perlasm/arm-xlate.pl new file mode 100755 index 0000000000..6e9b019987 --- /dev/null +++ b/external/boringssl/crypto/perlasm/arm-xlate.pl @@ -0,0 +1,172 @@ +#!/usr/bin/env perl + +# ARM assembler distiller by . + +my $flavour = shift; +my $output = shift; +open STDOUT,">$output" || die "can't open $output: $!"; + +$flavour = "linux32" if (!$flavour or $flavour eq "void"); + +my %GLOBALS; +my $dotinlocallabels=($flavour=~/linux/)?1:0; + +################################################################ +# directives which need special treatment on different platforms +################################################################ +my $arch = sub { + if ($flavour =~ /linux/) { ".arch\t".join(',',@_); } + else { ""; } +}; +my $fpu = sub { + if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); } + else { ""; } +}; +my $hidden = sub { + if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); } + else { ".hidden\t".join(',',@_); } +}; +my $comm = sub { + my @args = split(/,\s*/,shift); + my $name = @args[0]; + my $global = \$GLOBALS{$name}; + my $ret; + + if ($flavour =~ /ios32/) { + $ret = ".comm\t_$name,@args[1]\n"; + $ret .= ".non_lazy_symbol_pointer\n"; + $ret .= "$name:\n"; + $ret .= ".indirect_symbol\t_$name\n"; + $ret .= ".long\t0"; + $name = "_$name"; + } else { $ret = ".comm\t".join(',',@args); } + + $$global = $name; + $ret; +}; +my $globl = sub { + my $name = shift; + my $global = \$GLOBALS{$name}; + my $ret; + + SWITCH: for ($flavour) { + /ios/ && do { $name = "_$name"; + last; + }; + } + + $ret = ".globl $name\n"; + # All symbols in assembly files are hidden. + $ret .= &$hidden($name); + $$global = $name; + $ret; +}; +my $global = $globl; +my $extern = sub { + &$globl(@_); + return; # return nothing +}; +my $type = sub { + if ($flavour =~ /linux/) { ".type\t".join(',',@_); } + else { ""; } +}; +my $size = sub { + if ($flavour =~ /linux/) { ".size\t".join(',',@_); } + else { ""; } +}; +my $inst = sub { + if ($flavour =~ /linux/) { ".inst\t".join(',',@_); } + else { ".long\t".join(',',@_); } +}; +my $asciz = sub { + my $line = join(",",@_); + if ($line =~ /^"(.*)"$/) + { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } + else + { ""; } +}; + +sub range { + my ($r,$sfx,$start,$end) = @_; + + join(",",map("$r$_$sfx",($start..$end))); +} + +sub expand_line { + my $line = shift; + my @ret = (); + + pos($line)=0; + + while ($line =~ m/\G[^@\/\{\"]*/g) { + if ($line =~ m/\G(@|\/\/|$)/gc) { + last; + } + elsif ($line =~ m/\G\{/gc) { + my $saved_pos = pos($line); + $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e; + pos($line) = $saved_pos; + $line =~ m/\G[^\}]*\}/g; + } + elsif ($line =~ m/\G\"/gc) { + $line =~ m/\G[^\"]*\"/g; + } + } + + $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge; + + return $line; +} + +print "#if defined(__arm__)\n" if ($flavour eq "linux32"); +print "#if defined(__aarch64__)\n" if ($flavour eq "linux64"); + +while($line=<>) { + + if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; } + + $line =~ s|/\*.*\*/||; # get rid of C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning... + $line =~ s|\s+$||; # ... and at the end + + { + $line =~ s|[\b\.]L(\w{2,})|L$1|g; # common denominator for Locallabel + $line =~ s|\bL(\w{2,})|\.L$1|g if ($dotinlocallabels); + } + + { + $line =~ s|(^[\.\w]+)\:\s*||; + my $label = $1; + if ($label) { + printf "%s:",($GLOBALS{$label} or $label); + } + } + + if ($line !~ m/^[#@]/) { + $line =~ s|^\s*(\.?)(\S+)\s*||; + my $c = $1; $c = "\t" if ($c eq ""); + my $mnemonic = $2; + my $opcode; + if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) { + $opcode = eval("\$$1_$2"); + } else { + $opcode = eval("\$$mnemonic"); + } + + my $arg=expand_line($line); + + if (ref($opcode) eq 'CODE') { + $line = &$opcode($arg); + } elsif ($mnemonic) { + $line = $c.$mnemonic; + $line.= "\t$arg" if ($arg ne ""); + } + } + + print $line if ($line); + print "\n"; +} + +print "#endif\n" if ($flavour eq "linux32" || $flavour eq "linux64"); + +close STDOUT; diff --git a/external/boringssl/crypto/perlasm/cbc.pl b/external/boringssl/crypto/perlasm/cbc.pl new file mode 100644 index 0000000000..24561e759a --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/perlasm/readme b/external/boringssl/crypto/perlasm/readme new file mode 100644 index 0000000000..f02bbee75a --- /dev/null +++ b/external/boringssl/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. +# +# 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; + # TODO(davidben): Before supporting the + # mingw64 perlasm flavour, do away with this + # environment variable check. + die "mingw64 not supported"; + $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) { die "unknown flavour $flavour"; } + +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; + + $self->{value} =~ s/\b(0b[0-1]+)/oct($1)/eig; + if ($gas) { + # Solaris /usr/ccs/bin/as can't handle multiplications + # in $self->{value} + my $value = $self->{value}; + $value =~ s/(?{value} = $value; + } + sprintf "\$%s",$self->{value}; + } else { + $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/(?{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/(?{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/) { + if ($flavour eq "elf") { + $self->{value} .= "\n.hidden $line"; + } else { + $self->{value} = ""; + } + } 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/external/boringssl/crypto/perlasm/x86asm.pl b/external/boringssl/crypto/perlasm/x86asm.pl new file mode 100644 index 0000000000..3c7be40c02 --- /dev/null +++ b/external/boringssl/crypto/perlasm/x86asm.pl @@ -0,0 +1,292 @@ +#!/usr/bin/env perl + +# require 'x86asm.pl'; +# &asm_init(,"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/external/boringssl/crypto/perlasm/x86gas.pl b/external/boringssl/crypto/perlasm/x86gas.pl new file mode 100644 index 0000000000..55d09d8ba5 --- /dev/null +++ b/external/boringssl/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/^%[yxm]/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/external/boringssl/crypto/perlasm/x86masm.pl b/external/boringssl/crypto/perlasm/x86masm.pl new file mode 100644 index 0000000000..b7f49d1c41 --- /dev/null +++ b/external/boringssl/crypto/perlasm/x86masm.pl @@ -0,0 +1,200 @@ +#!/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/(?= 0x02030000\n"); + push(@out,"safeseh ".&::LABEL($nm,$nmdecor.$nm)."\n"); + push(@out,"%endif\n"); +} + +1; diff --git a/external/boringssl/crypto/pkcs8/CMakeLists.txt b/external/boringssl/crypto/pkcs8/CMakeLists.txt new file mode 100644 index 0000000000..8f674f915d --- /dev/null +++ b/external/boringssl/crypto/pkcs8/CMakeLists.txt @@ -0,0 +1,32 @@ +include_directories(../../include) + +add_library( + pkcs8_lib + + OBJECT + + pkcs8.c + p8_pkey.c + p5_pbe.c + p5_pbev2.c +) + +if(ENABLE_TESTS) +add_executable( + pkcs12_test + + pkcs12_test.cc + + $ +) + +add_executable( + pkcs8_test + + pkcs8_test.cc +) + +target_link_libraries(pkcs8_test crypto) +target_link_libraries(pkcs12_test crypto) +add_dependencies(all_tests pkcs8_test pkcs12_test) +endif() diff --git a/external/boringssl/crypto/pkcs8/internal.h b/external/boringssl/crypto/pkcs8/internal.h new file mode 100644 index 0000000000..7995e78745 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/internal.h @@ -0,0 +1,83 @@ +/* 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 + +#if defined(__cplusplus) +extern "C" { +#endif + + +#define PKCS5_DEFAULT_ITERATIONS 2048 +#define PKCS5_SALT_LEN 8 + +/* PKCS5_v2_PBE_keyivgen intializes the supplied |ctx| for PBKDF v2, which must + * be specified by |param|. The password is specified by |pass_raw| and + * |pass_raw_len|. |cipher| and |md| are ignored. + * + * It returns one on success and zero on error. */ +int PKCS5_v2_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 enc); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_PKCS8_INTERNAL_H */ diff --git a/external/boringssl/crypto/pkcs8/p5_pbe.c b/external/boringssl/crypto/pkcs8/p5_pbe.c new file mode 100644 index 0000000000..8e56d41b5c --- /dev/null +++ b/external/boringssl/crypto/pkcs8/p5_pbe.c @@ -0,0 +1,151 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "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, ERR_R_MALLOC_FAILURE); + goto err; + } + if(iter <= 0) + iter = PKCS5_DEFAULT_ITERATIONS; + if (!ASN1_INTEGER_set(pbe->iter, iter)) + { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!saltlen) + saltlen = PKCS5_SALT_LEN; + if (!ASN1_STRING_set(pbe->salt, NULL, saltlen)) + { + OPENSSL_PUT_ERROR(PKCS8, 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, 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, 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/external/boringssl/crypto/pkcs8/p5_pbev2.c b/external/boringssl/crypto/pkcs8/p5_pbev2.c new file mode 100644 index 0000000000..3799b39bf0 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/p5_pbev2.c @@ -0,0 +1,441 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999-2004. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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, 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, 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, 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, ERR_R_MALLOC_FAILURE); + PBKDF2PARAM_free(kdf); + X509_ALGOR_free(keyfunc); + return NULL; + } + +static int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, + const uint8_t *pass_raw, + size_t pass_raw_len, const ASN1_TYPE *param, + const ASN1_TYPE *iv, int enc) { + int rv = 0; + PBKDF2PARAM *pbkdf2param = NULL; + + if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { + OPENSSL_PUT_ERROR(PKCS8, CIPHER_R_NO_CIPHER_SET); + goto err; + } + + /* Decode parameters. */ + if (param == NULL || param->type != V_ASN1_SEQUENCE) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + const uint8_t *pbuf = param->value.sequence->data; + int plen = param->value.sequence->length; + pbkdf2param = d2i_PBKDF2PARAM(NULL, &pbuf, plen); + if (pbkdf2param == NULL || pbuf != param->value.sequence->data + plen) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + /* Now check the parameters. */ + uint8_t key[EVP_MAX_KEY_LENGTH]; + const size_t key_len = EVP_CIPHER_CTX_key_length(ctx); + assert(key_len <= sizeof(key)); + + if (pbkdf2param->keylength != NULL && + ASN1_INTEGER_get(pbkdf2param->keylength) != (int) key_len) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEYLENGTH); + goto err; + } + + if (pbkdf2param->prf != NULL && + OBJ_obj2nid(pbkdf2param->prf->algorithm) != NID_hmacWithSHA1) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF); + goto err; + } + + if (pbkdf2param->salt->type != V_ASN1_OCTET_STRING) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_SALT_TYPE); + goto err; + } + + if (pbkdf2param->iter->type != V_ASN1_INTEGER) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); + goto err; + } + long iterations = ASN1_INTEGER_get(pbkdf2param->iter); + if (iterations <= 0 || + (sizeof(long) > sizeof(unsigned) && iterations > (long)UINT_MAX)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); + goto err; + } + + if (iv->type != V_ASN1_OCTET_STRING || iv->value.octet_string == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS); + goto err; + } + + const size_t iv_len = EVP_CIPHER_CTX_iv_length(ctx); + if ((size_t) iv->value.octet_string->length != iv_len) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS); + goto err; + } + + if (!PKCS5_PBKDF2_HMAC_SHA1((const char *) pass_raw, pass_raw_len, + pbkdf2param->salt->value.octet_string->data, + pbkdf2param->salt->value.octet_string->length, + iterations, key_len, key)) { + goto err; + } + + rv = EVP_CipherInit_ex(ctx, NULL /* cipher */, NULL /* engine */, key, + iv->value.octet_string->data, enc); + + err: + PBKDF2PARAM_free(pbkdf2param); + return rv; +} + +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, + size_t pass_raw_len, ASN1_TYPE *param, + const EVP_CIPHER *unused, const EVP_MD *unused2, + int enc) { + PBE2PARAM *pbe2param = NULL; + int rv = 0; + + if (param == NULL || + param->type != V_ASN1_SEQUENCE || + param->value.sequence == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + const uint8_t *pbuf = param->value.sequence->data; + int plen = param->value.sequence->length; + pbe2param = d2i_PBE2PARAM(NULL, &pbuf, plen); + if (pbe2param == NULL || pbuf != param->value.sequence->data + plen) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + /* Check that the key derivation function is PBKDF2. */ + if (OBJ_obj2nid(pbe2param->keyfunc->algorithm) != NID_id_pbkdf2) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); + goto err; + } + + /* See if we recognise the encryption algorithm. */ + const EVP_CIPHER *cipher = + EVP_get_cipherbynid(OBJ_obj2nid(pbe2param->encryption->algorithm)); + if (cipher == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER); + goto err; + } + + /* Fixup cipher based on AlgorithmIdentifier. */ + if (!EVP_CipherInit_ex(ctx, cipher, NULL /* engine */, NULL /* key */, + NULL /* iv */, enc)) { + goto err; + } + + rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass_raw, pass_raw_len, + pbe2param->keyfunc->parameter, + pbe2param->encryption->parameter, enc); + + err: + PBE2PARAM_free(pbe2param); + return rv; +} diff --git a/external/boringssl/crypto/pkcs8/p8_pkey.c b/external/boringssl/crypto/pkcs8/p8_pkey.c new file mode 100644 index 0000000000..c69d0face2 --- /dev/null +++ b/external/boringssl/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 + +#include +#include +#include + +/* 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->type == V_ASN1_OCTET_STRING && + 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/external/boringssl/crypto/pkcs8/pkcs12_test.cc b/external/boringssl/crypto/pkcs8/pkcs12_test.cc new file mode 100644 index 0000000000..17bcd27372 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/pkcs12_test.cc @@ -0,0 +1,770 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.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 const char kPassword[] = "foo"; + +static bool Test(const char *name, const uint8_t *der, size_t der_len) { + ScopedX509Stack certs(sk_X509_new_null()); + if (!certs) { + return false; + } + + CBS pkcs12; + EVP_PKEY *key = nullptr; + CBS_init(&pkcs12, der, der_len); + if (!PKCS12_get_key_and_certs(&key, certs.get(), &pkcs12, kPassword)) { + fprintf(stderr, "PKCS12 failed on %s data.\n", name); + ERR_print_errors_fp(stderr); + return false; + } + ScopedEVP_PKEY delete_key(key); + + if (sk_X509_num(certs.get()) != 1 || key == nullptr) { + fprintf(stderr, "Bad result from %s data.\n", name); + return false; + } + + return true; +} + +static bool TestCompat(const uint8_t *der, size_t der_len) { + ScopedBIO bio(BIO_new_mem_buf(der, der_len)); + if (!bio) { + return false; + } + + ScopedPKCS12 p12(d2i_PKCS12_bio(bio.get(), nullptr)); + if (!p12) { + fprintf(stderr, "PKCS12_parse failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (PKCS12_verify_mac(p12.get(), "badpass", 7)) { + fprintf(stderr, "PKCS12_verify_mac accepted bad password.\n"); + return false; + } + + if (!PKCS12_verify_mac(p12.get(), kPassword, sizeof(kPassword) - 1)) { + fprintf(stderr, "PKCS12_verify_mac rejected good password.\n"); + return false; + } + + EVP_PKEY *key = nullptr; + X509 *cert = nullptr; + STACK_OF(X509) *ca_certs = nullptr; + if (!PKCS12_parse(p12.get(), kPassword, &key, &cert, &ca_certs)) { + fprintf(stderr, "PKCS12_parse failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + ScopedEVP_PKEY delete_key(key); + ScopedX509 delete_cert(cert); + ScopedX509Stack delete_ca_certs(ca_certs); + + if (key == nullptr || cert == nullptr) { + fprintf(stderr, "Bad result from PKCS12_parse.\n"); + return false; + } + + if (sk_X509_num(ca_certs) != 0) { + fprintf(stderr, "Bad result from PKCS12_parse.\n"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) || + !Test("NSS", kNSS, sizeof(kNSS)) || + !Test("Windows", kWindows, sizeof(kWindows)) || + !TestCompat(kWindows, sizeof(kWindows))) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/pkcs8/pkcs8.c b/external/boringssl/crypto/pkcs8/pkcs8.c new file mode 100644 index 0000000000..0ca0f2ec49 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/pkcs8.c @@ -0,0 +1,1227 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../bytestring/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; + + if (!ascii) { + *out = NULL; + *out_len = 0; + return 1; + } + + 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, + uint8_t id, int iterations, + size_t out_len, uint8_t *out, + const EVP_MD *md) { + /* See https://tools.ietf.org/html/rfc7292#appendix-B. Quoted parts of the + * specification have errata applied and other typos fixed. */ + + if (iterations < 1) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); + return 0; + } + + /* In the spec, |block_size| is called "v", but measured in bits. */ + size_t block_size = EVP_MD_block_size(md); + + /* 1. Construct a string, D (the "diversifier"), by concatenating v/8 copies + * of ID. */ + uint8_t D[EVP_MAX_MD_BLOCK_SIZE]; + memset(D, id, block_size); + + /* 2. Concatenate copies of the salt together to create a string S of length + * v(ceiling(s/v)) bits (the final copy of the salt may be truncated to + * create S). Note that if the salt is the empty string, then so is S. + * + * 3. Concatenate copies of the password together to create a string P of + * length v(ceiling(p/v)) bits (the final copy of the password may be + * truncated to create P). Note that if the password is the empty string, + * then so is P. + * + * 4. Set I=S||P to be the concatenation of S and P. */ + if (salt_len + block_size - 1 < salt_len || + pass_raw_len + block_size - 1 < pass_raw_len) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + size_t S_len = block_size * ((salt_len + block_size - 1) / block_size); + size_t P_len = block_size * ((pass_raw_len + block_size - 1) / block_size); + size_t I_len = S_len + P_len; + if (I_len < S_len) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + + uint8_t *I = OPENSSL_malloc(I_len); + if (I_len != 0 && I == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return 0; + } + + size_t i; + for (i = 0; i < S_len; i++) { + I[i] = salt[i % salt_len]; + } + for (i = 0; i < P_len; i++) { + I[i + S_len] = pass_raw[i % pass_raw_len]; + } + + int ret = 0; + EVP_MD_CTX ctx; + EVP_MD_CTX_init(&ctx); + + while (out_len != 0) { + /* A. Set A_i=H^r(D||I). (i.e., the r-th hash of D||I, + * H(H(H(... H(D||I)))) */ + uint8_t A[EVP_MAX_MD_SIZE]; + unsigned A_len; + if (!EVP_DigestInit_ex(&ctx, md, NULL) || + !EVP_DigestUpdate(&ctx, D, block_size) || + !EVP_DigestUpdate(&ctx, I, I_len) || + !EVP_DigestFinal_ex(&ctx, A, &A_len)) { + goto err; + } + int iter; + for (iter = 1; iter < iterations; iter++) { + if (!EVP_DigestInit_ex(&ctx, md, NULL) || + !EVP_DigestUpdate(&ctx, A, A_len) || + !EVP_DigestFinal_ex(&ctx, A, &A_len)) { + goto err; + } + } + + size_t todo = out_len < A_len ? out_len : A_len; + memcpy(out, A, todo); + out += todo; + out_len -= todo; + if (out_len == 0) { + break; + } + + /* B. Concatenate copies of A_i to create a string B of length v bits (the + * final copy of A_i may be truncated to create B). */ + uint8_t B[EVP_MAX_MD_BLOCK_SIZE]; + for (i = 0; i < block_size; i++) { + B[i] = A[i % A_len]; + } + + /* C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit blocks, + * where k=ceiling(s/v)+ceiling(p/v), modify I by setting I_j=(I_j+B+1) mod + * 2^v for each j. */ + assert(I_len % block_size == 0); + for (i = 0; i < I_len; i += block_size) { + unsigned carry = 1; + size_t j; + for (j = block_size - 1; j < block_size; j--) { + carry += I[i + j] + B[j]; + I[i + j] = (uint8_t)carry; + carry >>= 8; + } + } + } + + ret = 1; + +err: + OPENSSL_cleanse(I, I_len); + OPENSSL_free(I); + 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, 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, 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, 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, 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; + int flags; +}; + +#define PBE_UCS2_CONVERT_PASSWORD 0x1 + +static const struct pbe_suite kBuiltinPBE[] = { + { + NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc, EVP_sha1, + pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD + }, + { + NID_pbe_WithSHA1And128BitRC4, EVP_rc4, EVP_sha1, pkcs12_pbe_keyivgen, + PBE_UCS2_CONVERT_PASSWORD + }, + { + NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc, EVP_sha1, + pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD + }, + { + NID_pbes2, NULL, NULL, PKCS5_v2_PBE_keyivgen, 0 + }, +}; + +static const struct pbe_suite *get_pbe_suite(int pbe_nid) { + unsigned i; + for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(kBuiltinPBE[0]); i++) { + if (kBuiltinPBE[i].pbe_nid == pbe_nid) { + return &kBuiltinPBE[i]; + } + } + + return NULL; +} + +/* pass_to_pass_raw performs a password conversion (possibly a no-op) + * appropriate to the supplied |pbe_nid|. The input |pass| is treated as a + * NUL-terminated string if |pass_len| is -1, otherwise it is treated as a + * buffer of the specified length. If the supplied PBE NID sets the + * |PBE_UCS2_CONVERT_PASSWORD| flag, the supplied |pass| will be converted to + * UCS-2. + * + * It sets |*out_pass_raw| to a new buffer that must be freed by the caller. It + * returns one on success and zero on error. */ +static int pass_to_pass_raw(int pbe_nid, const char *pass, int pass_len, + uint8_t **out_pass_raw, size_t *out_pass_raw_len) { + if (pass == NULL) { + *out_pass_raw = NULL; + *out_pass_raw_len = 0; + return 1; + } + + if (pass_len == -1) { + pass_len = strlen(pass); + } else if (pass_len < 0 || pass_len > 2000000000) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + + const struct pbe_suite *suite = get_pbe_suite(pbe_nid); + if (suite != NULL && (suite->flags & PBE_UCS2_CONVERT_PASSWORD)) { + if (!ascii_to_ucs2(pass, pass_len, out_pass_raw, out_pass_raw_len)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + return 0; + } + } else { + *out_pass_raw = BUF_memdup(pass, pass_len); + if (*out_pass_raw == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return 0; + } + *out_pass_raw_len = (size_t)pass_len; + } + + return 1; +} + +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; + + const struct pbe_suite *suite = get_pbe_suite(OBJ_obj2nid(pbe_obj)); + if (suite == NULL) { + char obj_str[80]; + OPENSSL_PUT_ERROR(PKCS8, 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, PKCS8_R_UNKNOWN_CIPHER); + return 0; + } + } + + if (suite->md_func == NULL) { + md = NULL; + } else { + md = suite->md_func(); + if (!md) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_DIGEST); + return 0; + } + } + + if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md, + is_encrypt)) { + OPENSSL_PUT_ERROR(PKCS8, 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, 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, PKCS8_R_TOO_LONG); + goto err; + } + + buf = OPENSSL_malloc(in_len + block_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_CipherUpdate(&ctx, buf, &n, in, in_len)) { + OPENSSL_free(buf); + OPENSSL_PUT_ERROR(PKCS8, ERR_R_EVP_LIB); + goto err; + } + *out_len = n; + + if (!EVP_CipherFinal_ex(&ctx, buf + n, &n)) { + OPENSSL_free(buf); + OPENSSL_PUT_ERROR(PKCS8, 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, 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, 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; + if (!pass_to_pass_raw(OBJ_obj2nid(pkcs8->algor->algorithm), pass, pass_len, + &pass_raw, &pass_raw_len)) { + return NULL; + } + + PKCS8_PRIV_KEY_INFO *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, ERR_R_MALLOC_FAILURE); + return NULL; + } + in_len = ASN1_item_i2d(obj, &in, it); + if (!in) { + OPENSSL_PUT_ERROR(PKCS8, 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, 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; + if (!pass_to_pass_raw(pbe_nid, pass, pass_len, &pass_raw, &pass_raw_len)) { + return NULL; + } + + X509_SIG *ret = PKCS8_encrypt_pbe(pbe_nid, cipher, 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 EVP_CIPHER *cipher, + 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, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (pbe_nid == -1) { + pbe = PKCS5_pbe2_set(cipher, iterations, salt, salt_len); + } else { + pbe = PKCS5_pbe_set(pbe_nid, iterations, salt, salt_len); + } + if (!pbe) { + OPENSSL_PUT_ERROR(PKCS8, 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_R_ENCRYPT_ERROR); + goto err; + } + + return pkcs8; + +err: + X509_SIG_free(pkcs8); + return NULL; +} + +EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { + uint8_t *der = NULL; + int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der); + if (der_len < 0) { + return NULL; + } + + CBS cbs; + CBS_init(&cbs, der, (size_t)der_len); + EVP_PKEY *ret = EVP_parse_private_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + EVP_PKEY_free(ret); + OPENSSL_free(der); + return NULL; + } + + OPENSSL_free(der); + return ret; +} + +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) { + CBB cbb; + uint8_t *der = NULL; + size_t der_len; + if (!CBB_init(&cbb, 0) || + !EVP_marshal_private_key(&cbb, pkey) || + !CBB_finish(&cbb, &der, &der_len) || + der_len > LONG_MAX) { + CBB_cleanup(&cbb); + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR); + goto err; + } + + const uint8_t *p = der; + PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len); + if (p8 == NULL || p != der + der_len) { + PKCS8_PRIV_KEY_INFO_free(p8); + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + OPENSSL_free(der); + return p8; + +err: + OPENSSL_free(der); + 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, 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)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + 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, 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, 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: + 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; + uint8_t *storage = NULL; + + 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, 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_implicit_string( + &eci, &encrypted_contents, &storage, + CBS_ASN1_CONTEXT_SPECIFIC | 0, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data || + CBS_len(&ai) > LONG_MAX) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + inp = CBS_data(&ai); + algor = d2i_X509_ALGOR(NULL, &inp, (long)CBS_len(&ai)); + if (algor == NULL) { + goto err; + } + if (inp != CBS_data(&ai) + CBS_len(&ai)) { + X509_ALGOR_free(algor); + OPENSSL_PUT_ERROR(PKCS8, 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, 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, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12); + goto err; + } + + if (CBS_len(&wrapped_contents) > LONG_MAX) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + 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, (long)CBS_len(&wrapped_contents)); + if (encrypted == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) { + OPENSSL_PUT_ERROR(PKCS8, 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, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) { + if (CBS_len(&cert) > LONG_MAX) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + const uint8_t *inp = CBS_data(&cert); + X509 *x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert)); + if (!x509) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + if (inp != CBS_data(&cert) + CBS_len(&cert)) { + OPENSSL_PUT_ERROR(PKCS8, 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: + OPENSSL_free(storage); + 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)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + 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, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (version < 3) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_VERSION); + goto err; + } + + if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (CBS_len(&pfx) == 0) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MISSING_MAC); + goto err; + } + + if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(PKCS8, 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, 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, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED); + goto err; + } + + if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + ctx.out_key = out_key; + ctx.out_certs = out_certs; + if (!ascii_to_ucs2(password, password ? strlen(password) : 0, &ctx.password, + &ctx.password_len)) { + OPENSSL_PUT_ERROR(PKCS8, 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, 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, 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, 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, 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: + OPENSSL_free(ctx.password); + OPENSSL_free(der_bytes); + if (!ret) { + 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; + + 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; + + if (out_p12) { + PKCS12_free(*out_p12); + + *out_p12 = p12; + } + + 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) { + if (used == 0) { + goto out; + } + /* Workaround a bug in node.js. It uses a memory BIO for this in the wrong + * mode. */ + n = 0; + } + + 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) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + 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; +} + +int PKCS12_verify_mac(const PKCS12 *p12, const char *password, + int password_len) { + if (password == NULL) { + if (password_len != 0) { + return 0; + } + } else if (password_len != -1 && + (password[password_len] != 0 || + memchr(password, 0, password_len) != NULL)) { + return 0; + } + + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) { + ERR_clear_error(); + return 0; + } + + EVP_PKEY_free(pkey); + X509_free(cert); + + return 1; +} + +void PKCS12_free(PKCS12 *p12) { + if (p12 == NULL) { + return; + } + OPENSSL_free(p12->ber_bytes); + OPENSSL_free(p12); +} diff --git a/external/boringssl/crypto/pkcs8/pkcs8_test.cc b/external/boringssl/crypto/pkcs8/pkcs8_test.cc new file mode 100644 index 0000000000..7a88ddf4f0 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/pkcs8_test.cc @@ -0,0 +1,91 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +/* kDER is a PKCS#8 encrypted private key. It was generated with: + * + * openssl genrsa 512 > test.key + * openssl pkcs8 -topk8 -in test.key -out test.key.encrypted -v2 des3 -outform der + * hexdump -Cv test.key.encrypted + * + * The password is "testing". + */ +static const uint8_t kDER[] = { + 0x30, 0x82, 0x01, 0x9e, 0x30, 0x40, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x33, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x0e, 0x04, 0x08, 0x06, 0xa5, 0x4b, 0x0c, 0x0c, 0x50, 0x8c, 0x19, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x3a, 0xd0, + 0x70, 0x4b, 0x26, 0x50, 0x13, 0x7b, 0x04, 0x82, 0x01, 0x58, 0xa6, 0xee, 0x02, 0xf2, 0xf2, 0x7c, + 0x19, 0x91, 0xe3, 0xce, 0x32, 0x85, 0xc5, 0x01, 0xd9, 0xe3, 0x5e, 0x14, 0xb6, 0xb8, 0x78, 0xad, + 0xda, 0x01, 0xec, 0x9e, 0x42, 0xe8, 0xbf, 0x0b, 0x46, 0x03, 0xbc, 0x92, 0x6f, 0xe4, 0x0f, 0x0f, + 0x48, 0x30, 0x10, 0x10, 0x9b, 0xfb, 0x4b, 0xb9, 0x45, 0xf8, 0xcf, 0xab, 0xa1, 0x18, 0xdd, 0x19, + 0xa4, 0xa4, 0xe1, 0xf0, 0xa1, 0x8d, 0xc2, 0x23, 0xe7, 0x0d, 0x7a, 0x64, 0x21, 0x6b, 0xfa, 0x48, + 0xb9, 0x41, 0xc1, 0x0c, 0x4b, 0xce, 0x6f, 0x1a, 0x91, 0x9b, 0x9f, 0xdd, 0xcf, 0xa9, 0x8d, 0x33, + 0x2c, 0x45, 0x81, 0x5c, 0x5e, 0x67, 0xc6, 0x68, 0x43, 0x62, 0xff, 0x5e, 0x9b, 0x1a, 0x15, 0x3a, + 0x9d, 0x71, 0x3f, 0xbe, 0x32, 0x2f, 0xe5, 0x90, 0x65, 0x65, 0x9c, 0x22, 0xf6, 0x29, 0x2e, 0xcf, + 0x26, 0x16, 0x7b, 0x66, 0x48, 0x55, 0xad, 0x9a, 0x8d, 0x89, 0xf4, 0x48, 0x4f, 0x1f, 0x9d, 0xb8, + 0xfa, 0xe1, 0xf1, 0x3b, 0x39, 0x5c, 0x72, 0xc6, 0xb8, 0x3e, 0x98, 0xe8, 0x77, 0xe8, 0xb6, 0x71, + 0x84, 0xa8, 0x6e, 0xca, 0xaf, 0x62, 0x96, 0x49, 0x8a, 0x21, 0x6f, 0x9e, 0x78, 0x07, 0x97, 0x38, + 0x40, 0x66, 0x42, 0x5a, 0x1b, 0xe0, 0x9b, 0xe9, 0x91, 0x82, 0xe4, 0xea, 0x8f, 0x2a, 0xb2, 0x80, + 0xce, 0xe8, 0x57, 0xd3, 0xac, 0x11, 0x9d, 0xb2, 0x39, 0x0f, 0xe1, 0xce, 0x18, 0x96, 0x38, 0xa1, + 0x19, 0x80, 0x88, 0x81, 0x3d, 0xda, 0xaa, 0x8e, 0x15, 0x27, 0x19, 0x73, 0x0c, 0xf3, 0xaf, 0x45, + 0xe9, 0x1b, 0xad, 0x6c, 0x3d, 0xbf, 0x95, 0xf7, 0xa0, 0x87, 0x0e, 0xde, 0xf1, 0xd8, 0xee, 0xaa, + 0x92, 0x76, 0x8d, 0x32, 0x45, 0xa1, 0xe7, 0xf5, 0x05, 0xd6, 0x2c, 0x67, 0x63, 0x10, 0xfa, 0xde, + 0x80, 0xc7, 0x5b, 0x96, 0x0f, 0x24, 0x50, 0x78, 0x30, 0xe5, 0x89, 0xf3, 0x73, 0xfa, 0x40, 0x11, + 0xd5, 0x26, 0xb8, 0x36, 0x96, 0x98, 0xe6, 0xbd, 0x73, 0x62, 0x56, 0xb9, 0xea, 0x28, 0x16, 0x93, + 0x5b, 0x33, 0xae, 0x83, 0xf9, 0x1f, 0xee, 0xef, 0xc8, 0xbf, 0xc7, 0xb1, 0x47, 0x43, 0xa1, 0xc6, + 0x1a, 0x64, 0x47, 0x02, 0x40, 0x3e, 0xbc, 0x0f, 0x80, 0x71, 0x5c, 0x44, 0x60, 0xbc, 0x78, 0x2e, + 0xd2, 0x77, 0xf8, 0x6e, 0x12, 0x51, 0x89, 0xdb, 0x90, 0x64, 0xcd, 0x76, 0x10, 0x29, 0x73, 0xc2, + 0x2f, 0x94, 0x7b, 0x98, 0xcd, 0xbb, 0x61, 0x16, 0x1d, 0x52, 0x11, 0x73, 0x48, 0xe6, 0x39, 0xfc, + 0xd6, 0x2d, +}; + +static bool test(const uint8_t *der, size_t der_len) { + const uint8_t *data = der; + ScopedX509_SIG sig(d2i_X509_SIG(NULL, &data, der_len)); + if (sig.get() == NULL || data != der + der_len) { + fprintf(stderr, "d2i_X509_SIG failed or did not consume all bytes.\n"); + return false; + } + + static const char kPassword[] = "testing"; + ScopedPKCS8_PRIV_KEY_INFO keypair(PKCS8_decrypt(sig.get(), kPassword, -1)); + if (!keypair) { + fprintf(stderr, "PKCS8_decrypt failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + if (!test(kDER, sizeof(kDER))) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/poly1305/CMakeLists.txt b/external/boringssl/crypto/poly1305/CMakeLists.txt new file mode 100644 index 0000000000..e1d5c74607 --- /dev/null +++ b/external/boringssl/crypto/poly1305/CMakeLists.txt @@ -0,0 +1,33 @@ +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} +) + +if(ENABLE_TESTS) +add_executable( + poly1305_test + + poly1305_test.cc + $ +) + +target_link_libraries(poly1305_test crypto) +add_dependencies(all_tests poly1305_test) +endif() diff --git a/external/boringssl/crypto/poly1305/asm/poly1305-armv4.pl b/external/boringssl/crypto/poly1305/asm/poly1305-armv4.pl new file mode 100755 index 0000000000..9b765cec69 --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-armv4.pl @@ -0,0 +1,1216 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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/. +# ==================================================================== +# +# IALU(*)/gcc-4.4 NEON +# +# ARM11xx(ARMv6) 7.78/+100% - +# Cortex-A5 6.30/+130% 2.96 +# Cortex-A8 6.25/+115% 2.36 +# Cortex-A9 5.10/+95% 2.55 +# Cortex-A15 3.79/+85% 1.25(**) +# Snapdragon S4 5.70/+100% 1.48(**) +# +# (*) this is for -march=armv6, i.e. with bunch of ldrb loading data; +# (**) these are trade-off results, they can be improved by ~8% but at +# the cost of 15/12% regression on Cortex-A5/A7, it's even possible +# to improve Cortex-A9 result, but then A5/A7 loose more than 20%; + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +($ctx,$inp,$len,$padbit)=map("r$_",(0..3)); + +$code.=<<___; +#include + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +.globl poly1305_emit +.globl poly1305_blocks +.globl poly1305_init +.type poly1305_init,%function +.align 5 +poly1305_init: +.Lpoly1305_init: + stmdb sp!,{r4-r11} + + eor r3,r3,r3 + cmp $inp,#0 + str r3,[$ctx,#0] @ zero hash value + str r3,[$ctx,#4] + str r3,[$ctx,#8] + str r3,[$ctx,#12] + str r3,[$ctx,#16] + str r3,[$ctx,#36] @ is_base2_26 + add $ctx,$ctx,#20 + +#ifdef __thumb2__ + it eq +#endif + moveq r0,#0 + beq .Lno_key + +#if __ARM_MAX_ARCH__>=7 + adr r11,.Lpoly1305_init + ldr r12,.LOPENSSL_armcap +#endif + ldrb r4,[$inp,#0] + mov r10,#0x0fffffff + ldrb r5,[$inp,#1] + and r3,r10,#-4 @ 0x0ffffffc + ldrb r6,[$inp,#2] + ldrb r7,[$inp,#3] + orr r4,r4,r5,lsl#8 + ldrb r5,[$inp,#4] + orr r4,r4,r6,lsl#16 + ldrb r6,[$inp,#5] + orr r4,r4,r7,lsl#24 + ldrb r7,[$inp,#6] + and r4,r4,r10 + +#if __ARM_MAX_ARCH__>=7 + ldr r12,[r11,r12] @ OPENSSL_armcap_P +# ifdef __APPLE__ + ldr r12,[r12] +# endif +#endif + ldrb r8,[$inp,#7] + orr r5,r5,r6,lsl#8 + ldrb r6,[$inp,#8] + orr r5,r5,r7,lsl#16 + ldrb r7,[$inp,#9] + orr r5,r5,r8,lsl#24 + ldrb r8,[$inp,#10] + and r5,r5,r3 + +#if __ARM_MAX_ARCH__>=7 + tst r12,#ARMV7_NEON @ check for NEON +# ifdef __APPLE__ + adr r9,poly1305_blocks_neon + adr r11,poly1305_blocks +# ifdef __thumb2__ + it ne +# endif + movne r11,r9 + adr r12,poly1305_emit + adr r10,poly1305_emit_neon +# ifdef __thumb2__ + it ne +# endif + movne r12,r10 +# else +# ifdef __thumb2__ + itete eq +# endif + addeq r12,r11,#(poly1305_emit-.Lpoly1305_init) + addne r12,r11,#(poly1305_emit_neon-.Lpoly1305_init) + addeq r11,r11,#(poly1305_blocks-.Lpoly1305_init) + addne r11,r11,#(poly1305_blocks_neon-.Lpoly1305_init) +# endif +# ifdef __thumb2__ + orr r12,r12,#1 @ thumb-ify address + orr r11,r11,#1 +# endif +#endif + ldrb r9,[$inp,#11] + orr r6,r6,r7,lsl#8 + ldrb r7,[$inp,#12] + orr r6,r6,r8,lsl#16 + ldrb r8,[$inp,#13] + orr r6,r6,r9,lsl#24 + ldrb r9,[$inp,#14] + and r6,r6,r3 + + ldrb r10,[$inp,#15] + orr r7,r7,r8,lsl#8 + str r4,[$ctx,#0] + orr r7,r7,r9,lsl#16 + str r5,[$ctx,#4] + orr r7,r7,r10,lsl#24 + str r6,[$ctx,#8] + and r7,r7,r3 + str r7,[$ctx,#12] +#if __ARM_MAX_ARCH__>=7 + stmia r2,{r11,r12} @ fill functions table + mov r0,#1 +#else + mov r0,#0 +#endif +.Lno_key: + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_init,.-poly1305_init +___ +{ +my ($h0,$h1,$h2,$h3,$h4,$r0,$r1,$r2,$r3)=map("r$_",(4..12)); +my ($s1,$s2,$s3)=($r1,$r2,$r3); + +$code.=<<___; +.type poly1305_blocks,%function +.align 5 +poly1305_blocks: + stmdb sp!,{r3-r11,lr} + + ands $len,$len,#-16 + beq .Lno_data + + cmp $padbit,#0 + add $len,$len,$inp @ end pointer + sub sp,sp,#32 + + ldmia $ctx,{$h0-$r3} @ load context + + str $ctx,[sp,#12] @ offload stuff + mov lr,$inp + str $len,[sp,#16] + str $r1,[sp,#20] + str $r2,[sp,#24] + str $r3,[sp,#28] + b .Loop + +.Loop: +#if __ARM_ARCH__<7 + ldrb r0,[lr],#16 @ load input +# ifdef __thumb2__ + it hi +# endif + addhi $h4,$h4,#1 @ 1<<128 + ldrb r1,[lr,#-15] + ldrb r2,[lr,#-14] + ldrb r3,[lr,#-13] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-12] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-11] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-10] + adds $h0,$h0,r3 @ accumulate input + + ldrb r3,[lr,#-9] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-8] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-7] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-6] + adcs $h1,$h1,r3 + + ldrb r3,[lr,#-5] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-4] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-3] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-2] + adcs $h2,$h2,r3 + + ldrb r3,[lr,#-1] + orr r1,r0,r1,lsl#8 + str lr,[sp,#8] @ offload input pointer + orr r2,r1,r2,lsl#16 + add $s1,$r1,$r1,lsr#2 + orr r3,r2,r3,lsl#24 +#else + ldr r0,[lr],#16 @ load input +# ifdef __thumb2__ + it hi +# endif + addhi $h4,$h4,#1 @ padbit + ldr r1,[lr,#-12] + ldr r2,[lr,#-8] + ldr r3,[lr,#-4] +# ifdef __ARMEB__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +# endif + adds $h0,$h0,r0 @ accumulate input + str lr,[sp,#8] @ offload input pointer + adcs $h1,$h1,r1 + add $s1,$r1,$r1,lsr#2 + adcs $h2,$h2,r2 +#endif + add $s2,$r2,$r2,lsr#2 + adcs $h3,$h3,r3 + add $s3,$r3,$r3,lsr#2 + + umull r2,r3,$h1,$r0 + adc $h4,$h4,#0 + umull r0,r1,$h0,$r0 + umlal r2,r3,$h4,$s1 + umlal r0,r1,$h3,$s1 + ldr $r1,[sp,#20] @ reload $r1 + umlal r2,r3,$h2,$s3 + umlal r0,r1,$h1,$s3 + umlal r2,r3,$h3,$s2 + umlal r0,r1,$h2,$s2 + umlal r2,r3,$h0,$r1 + str r0,[sp,#0] @ future $h0 + mul r0,$s2,$h4 + ldr $r2,[sp,#24] @ reload $r2 + adds r2,r2,r1 @ d1+=d0>>32 + eor r1,r1,r1 + adc lr,r3,#0 @ future $h2 + str r2,[sp,#4] @ future $h1 + + mul r2,$s3,$h4 + eor r3,r3,r3 + umlal r0,r1,$h3,$s3 + ldr $r3,[sp,#28] @ reload $r3 + umlal r2,r3,$h3,$r0 + umlal r0,r1,$h2,$r0 + umlal r2,r3,$h2,$r1 + umlal r0,r1,$h1,$r1 + umlal r2,r3,$h1,$r2 + umlal r0,r1,$h0,$r2 + umlal r2,r3,$h0,$r3 + ldr $h0,[sp,#0] + mul $h4,$r0,$h4 + ldr $h1,[sp,#4] + + adds $h2,lr,r0 @ d2+=d1>>32 + ldr lr,[sp,#8] @ reload input pointer + adc r1,r1,#0 + adds $h3,r2,r1 @ d3+=d2>>32 + ldr r0,[sp,#16] @ reload end pointer + adc r3,r3,#0 + add $h4,$h4,r3 @ h4+=d3>>32 + + and r1,$h4,#-4 + and $h4,$h4,#3 + add r1,r1,r1,lsr#2 @ *=5 + adds $h0,$h0,r1 + adcs $h1,$h1,#0 + adcs $h2,$h2,#0 + adc $h3,$h3,#0 + + cmp r0,lr @ done yet? + bhi .Loop + + ldr $ctx,[sp,#12] + add sp,sp,#32 + stmia $ctx,{$h0-$h4} @ store the result + +.Lno_data: +#if __ARM_ARCH__>=5 + ldmia sp!,{r3-r11,pc} +#else + ldmia sp!,{r3-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_blocks,.-poly1305_blocks +___ +} +{ +my ($ctx,$mac,$nonce)=map("r$_",(0..2)); +my ($h0,$h1,$h2,$h3,$h4,$g0,$g1,$g2,$g3)=map("r$_",(3..11)); +my $g4=$h4; + +$code.=<<___; +.type poly1305_emit,%function +.align 5 +poly1305_emit: + stmdb sp!,{r4-r11} +.Lpoly1305_emit_enter: + + ldmia $ctx,{$h0-$h4} + adds $g0,$h0,#5 @ compare to modulus + adcs $g1,$h1,#0 + adcs $g2,$h2,#0 + adcs $g3,$h3,#0 + adc $g4,$h4,#0 + tst $g4,#4 @ did it carry/borrow? + +#ifdef __thumb2__ + it ne +#endif + movne $h0,$g0 + ldr $g0,[$nonce,#0] +#ifdef __thumb2__ + it ne +#endif + movne $h1,$g1 + ldr $g1,[$nonce,#4] +#ifdef __thumb2__ + it ne +#endif + movne $h2,$g2 + ldr $g2,[$nonce,#8] +#ifdef __thumb2__ + it ne +#endif + movne $h3,$g3 + ldr $g3,[$nonce,#12] + + adds $h0,$h0,$g0 + adcs $h1,$h1,$g1 + adcs $h2,$h2,$g2 + adc $h3,$h3,$g3 + +#if __ARM_ARCH__>=7 +# ifdef __ARMEB__ + rev $h0,$h0 + rev $h1,$h1 + rev $h2,$h2 + rev $h3,$h3 +# endif + str $h0,[$mac,#0] + str $h1,[$mac,#4] + str $h2,[$mac,#8] + str $h3,[$mac,#12] +#else + strb $h0,[$mac,#0] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#4] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#8] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#12] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#1] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#5] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#9] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#13] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#2] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#6] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#10] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#14] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#3] + strb $h1,[$mac,#7] + strb $h2,[$mac,#11] + strb $h3,[$mac,#15] +#endif + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_emit,.-poly1305_emit +___ +{ +my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("d$_",(0..9)); +my ($D0,$D1,$D2,$D3,$D4, $H0,$H1,$H2,$H3,$H4) = map("q$_",(5..14)); +my ($T0,$T1,$MASK) = map("q$_",(15,4,0)); + +my ($in2,$zeros,$tbl0,$tbl1) = map("r$_",(4..7)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.fpu neon + +.type poly1305_init_neon,%function +.align 5 +poly1305_init_neon: + ldr r4,[$ctx,#20] @ load key base 2^32 + ldr r5,[$ctx,#24] + ldr r6,[$ctx,#28] + ldr r7,[$ctx,#32] + + and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 + mov r3,r4,lsr#26 + mov r4,r5,lsr#20 + orr r3,r3,r5,lsl#6 + mov r5,r6,lsr#14 + orr r4,r4,r6,lsl#12 + mov r6,r7,lsr#8 + orr r5,r5,r7,lsl#18 + and r3,r3,#0x03ffffff + and r4,r4,#0x03ffffff + and r5,r5,#0x03ffffff + + vdup.32 $R0,r2 @ r^1 in both lanes + add r2,r3,r3,lsl#2 @ *5 + vdup.32 $R1,r3 + add r3,r4,r4,lsl#2 + vdup.32 $S1,r2 + vdup.32 $R2,r4 + add r4,r5,r5,lsl#2 + vdup.32 $S2,r3 + vdup.32 $R3,r5 + add r5,r6,r6,lsl#2 + vdup.32 $S3,r4 + vdup.32 $R4,r6 + vdup.32 $S4,r5 + + mov $zeros,#2 @ counter + +.Lsquare_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + + vmull.u32 $D0,$R0,${R0}[1] + vmull.u32 $D1,$R1,${R0}[1] + vmull.u32 $D2,$R2,${R0}[1] + vmull.u32 $D3,$R3,${R0}[1] + vmull.u32 $D4,$R4,${R0}[1] + + vmlal.u32 $D0,$R4,${S1}[1] + vmlal.u32 $D1,$R0,${R1}[1] + vmlal.u32 $D2,$R1,${R1}[1] + vmlal.u32 $D3,$R2,${R1}[1] + vmlal.u32 $D4,$R3,${R1}[1] + + vmlal.u32 $D0,$R3,${S2}[1] + vmlal.u32 $D1,$R4,${S2}[1] + vmlal.u32 $D3,$R1,${R2}[1] + vmlal.u32 $D2,$R0,${R2}[1] + vmlal.u32 $D4,$R2,${R2}[1] + + vmlal.u32 $D0,$R2,${S3}[1] + vmlal.u32 $D3,$R0,${R3}[1] + vmlal.u32 $D1,$R3,${S3}[1] + vmlal.u32 $D2,$R4,${S3}[1] + vmlal.u32 $D4,$R1,${R3}[1] + + vmlal.u32 $D3,$R4,${S4}[1] + vmlal.u32 $D0,$R1,${S4}[1] + vmlal.u32 $D1,$R2,${S4}[1] + vmlal.u32 $D2,$R3,${S4}[1] + vmlal.u32 $D4,$R0,${R4}[1] + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + @ and P. Schwabe + + vshr.u64 $T0,$D3,#26 + vmovn.i64 $D3#lo,$D3 + vshr.u64 $T1,$D0,#26 + vmovn.i64 $D0#lo,$D0 + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vbic.i32 $D3#lo,#0xfc000000 @ &=0x03ffffff + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + vbic.i32 $D0#lo,#0xfc000000 + + vshrn.u64 $T0#lo,$D4,#26 + vmovn.i64 $D4#lo,$D4 + vshr.u64 $T1,$D1,#26 + vmovn.i64 $D1#lo,$D1 + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + vbic.i32 $D4#lo,#0xfc000000 + vbic.i32 $D1#lo,#0xfc000000 + + vadd.i32 $D0#lo,$D0#lo,$T0#lo + vshl.u32 $T0#lo,$T0#lo,#2 + vshrn.u64 $T1#lo,$D2,#26 + vmovn.i64 $D2#lo,$D2 + vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0 + vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3 + vbic.i32 $D2#lo,#0xfc000000 + + vshr.u32 $T0#lo,$D0#lo,#26 + vbic.i32 $D0#lo,#0xfc000000 + vshr.u32 $T1#lo,$D3#lo,#26 + vbic.i32 $D3#lo,#0xfc000000 + vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1 + vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4 + + subs $zeros,$zeros,#1 + beq .Lsquare_break_neon + + add $tbl0,$ctx,#(48+0*9*4) + add $tbl1,$ctx,#(48+1*9*4) + + vtrn.32 $R0,$D0#lo @ r^2:r^1 + vtrn.32 $R2,$D2#lo + vtrn.32 $R3,$D3#lo + vtrn.32 $R1,$D1#lo + vtrn.32 $R4,$D4#lo + + vshl.u32 $S2,$R2,#2 @ *5 + vshl.u32 $S3,$R3,#2 + vshl.u32 $S1,$R1,#2 + vshl.u32 $S4,$R4,#2 + vadd.i32 $S2,$S2,$R2 + vadd.i32 $S1,$S1,$R1 + vadd.i32 $S3,$S3,$R3 + vadd.i32 $S4,$S4,$R4 + + vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! + vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! + vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vst1.32 {${S4}[0]},[$tbl0,:32] + vst1.32 {${S4}[1]},[$tbl1,:32] + + b .Lsquare_neon + +.align 4 +.Lsquare_break_neon: + add $tbl0,$ctx,#(48+2*4*9) + add $tbl1,$ctx,#(48+3*4*9) + + vmov $R0,$D0#lo @ r^4:r^3 + vshl.u32 $S1,$D1#lo,#2 @ *5 + vmov $R1,$D1#lo + vshl.u32 $S2,$D2#lo,#2 + vmov $R2,$D2#lo + vshl.u32 $S3,$D3#lo,#2 + vmov $R3,$D3#lo + vshl.u32 $S4,$D4#lo,#2 + vmov $R4,$D4#lo + vadd.i32 $S1,$S1,$D1#lo + vadd.i32 $S2,$S2,$D2#lo + vadd.i32 $S3,$S3,$D3#lo + vadd.i32 $S4,$S4,$D4#lo + + vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! + vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! + vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vst1.32 {${S4}[0]},[$tbl0] + vst1.32 {${S4}[1]},[$tbl1] + + ret @ bx lr +.size poly1305_init_neon,.-poly1305_init_neon + +.type poly1305_blocks_neon,%function +.align 5 +poly1305_blocks_neon: + ldr ip,[$ctx,#36] @ is_base2_26 + ands $len,$len,#-16 + beq .Lno_data_neon + + cmp $len,#64 + bhs .Lenter_neon + tst ip,ip @ is_base2_26? + beq poly1305_blocks + +.Lenter_neon: + stmdb sp!,{r4-r7} + vstmdb sp!,{d8-d15} @ ABI specification says so + + tst ip,ip @ is_base2_26? + bne .Lbase2_26_neon + + stmdb sp!,{r1-r3,lr} + bl poly1305_init_neon + + ldr r4,[$ctx,#0] @ load hash value base 2^32 + ldr r5,[$ctx,#4] + ldr r6,[$ctx,#8] + ldr r7,[$ctx,#12] + ldr ip,[$ctx,#16] + + and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 + mov r3,r4,lsr#26 + veor $D0#lo,$D0#lo,$D0#lo + mov r4,r5,lsr#20 + orr r3,r3,r5,lsl#6 + veor $D1#lo,$D1#lo,$D1#lo + mov r5,r6,lsr#14 + orr r4,r4,r6,lsl#12 + veor $D2#lo,$D2#lo,$D2#lo + mov r6,r7,lsr#8 + orr r5,r5,r7,lsl#18 + veor $D3#lo,$D3#lo,$D3#lo + and r3,r3,#0x03ffffff + orr r6,r6,ip,lsl#24 + veor $D4#lo,$D4#lo,$D4#lo + and r4,r4,#0x03ffffff + mov r1,#1 + and r5,r5,#0x03ffffff + str r1,[$ctx,#36] @ is_base2_26 + + vmov.32 $D0#lo[0],r2 + vmov.32 $D1#lo[0],r3 + vmov.32 $D2#lo[0],r4 + vmov.32 $D3#lo[0],r5 + vmov.32 $D4#lo[0],r6 + adr $zeros,.Lzeros + + ldmia sp!,{r1-r3,lr} + b .Lbase2_32_neon + +.align 4 +.Lbase2_26_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ load hash value + + veor $D0#lo,$D0#lo,$D0#lo + veor $D1#lo,$D1#lo,$D1#lo + veor $D2#lo,$D2#lo,$D2#lo + veor $D3#lo,$D3#lo,$D3#lo + veor $D4#lo,$D4#lo,$D4#lo + vld4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]! + adr $zeros,.Lzeros + vld1.32 {$D4#lo[0]},[$ctx] + sub $ctx,$ctx,#16 @ rewind + +.Lbase2_32_neon: + add $in2,$inp,#32 + mov $padbit,$padbit,lsl#24 + tst $len,#31 + beq .Leven + + vld4.32 {$H0#lo[0],$H1#lo[0],$H2#lo[0],$H3#lo[0]},[$inp]! + vmov.32 $H4#lo[0],$padbit + sub $len,$len,#16 + add $in2,$inp,#32 + +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H3,$H3 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 +# endif + vsri.u32 $H4#lo,$H3#lo,#8 @ base 2^32 -> base 2^26 + vshl.u32 $H3#lo,$H3#lo,#18 + + vsri.u32 $H3#lo,$H2#lo,#14 + vshl.u32 $H2#lo,$H2#lo,#12 + vadd.i32 $H4#hi,$H4#lo,$D4#lo @ add hash value and move to #hi + + vbic.i32 $H3#lo,#0xfc000000 + vsri.u32 $H2#lo,$H1#lo,#20 + vshl.u32 $H1#lo,$H1#lo,#6 + + vbic.i32 $H2#lo,#0xfc000000 + vsri.u32 $H1#lo,$H0#lo,#26 + vadd.i32 $H3#hi,$H3#lo,$D3#lo + + vbic.i32 $H0#lo,#0xfc000000 + vbic.i32 $H1#lo,#0xfc000000 + vadd.i32 $H2#hi,$H2#lo,$D2#lo + + vadd.i32 $H0#hi,$H0#lo,$D0#lo + vadd.i32 $H1#hi,$H1#lo,$D1#lo + + mov $tbl1,$zeros + add $tbl0,$ctx,#48 + + cmp $len,$len + b .Long_tail + +.align 4 +.Leven: + subs $len,$len,#64 +# ifdef __thumb2__ + it lo +# endif + movlo $in2,$zeros + + vmov.i32 $H4,#1<<24 @ padbit, yes, always + vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1] + add $inp,$inp,#64 + vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0) + add $in2,$in2,#64 +# ifdef __thumb2__ + itt hi +# endif + addhi $tbl1,$ctx,#(48+1*9*4) + addhi $tbl0,$ctx,#(48+3*9*4) + +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H3,$H3 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 +# endif + vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26 + vshl.u32 $H3,$H3,#18 + + vsri.u32 $H3,$H2,#14 + vshl.u32 $H2,$H2,#12 + + vbic.i32 $H3,#0xfc000000 + vsri.u32 $H2,$H1,#20 + vshl.u32 $H1,$H1,#6 + + vbic.i32 $H2,#0xfc000000 + vsri.u32 $H1,$H0,#26 + + vbic.i32 $H0,#0xfc000000 + vbic.i32 $H1,#0xfc000000 + + bls .Lskip_loop + + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^2 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + b .Loop_neon + +.align 5 +.Loop_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + @ \___________________/ + @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + @ \___________________/ \____________________/ + @ + @ Note that we start with inp[2:3]*r^2. This is because it + @ doesn't depend on reduction in previous iteration. + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ inp[2:3]*r^2 + + vadd.i32 $H2#lo,$H2#lo,$D2#lo @ accumulate inp[0:1] + vmull.u32 $D2,$H2#hi,${R0}[1] + vadd.i32 $H0#lo,$H0#lo,$D0#lo + vmull.u32 $D0,$H0#hi,${R0}[1] + vadd.i32 $H3#lo,$H3#lo,$D3#lo + vmull.u32 $D3,$H3#hi,${R0}[1] + vmlal.u32 $D2,$H1#hi,${R1}[1] + vadd.i32 $H1#lo,$H1#lo,$D1#lo + vmull.u32 $D1,$H1#hi,${R0}[1] + + vadd.i32 $H4#lo,$H4#lo,$D4#lo + vmull.u32 $D4,$H4#hi,${R0}[1] + subs $len,$len,#64 + vmlal.u32 $D0,$H4#hi,${S1}[1] +# ifdef __thumb2__ + it lo +# endif + movlo $in2,$zeros + vmlal.u32 $D3,$H2#hi,${R1}[1] + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D1,$H0#hi,${R1}[1] + vmlal.u32 $D4,$H3#hi,${R1}[1] + + vmlal.u32 $D0,$H3#hi,${S2}[1] + vmlal.u32 $D3,$H1#hi,${R2}[1] + vmlal.u32 $D4,$H2#hi,${R2}[1] + vmlal.u32 $D1,$H4#hi,${S2}[1] + vmlal.u32 $D2,$H0#hi,${R2}[1] + + vmlal.u32 $D3,$H0#hi,${R3}[1] + vmlal.u32 $D0,$H2#hi,${S3}[1] + vmlal.u32 $D4,$H1#hi,${R3}[1] + vmlal.u32 $D1,$H3#hi,${S3}[1] + vmlal.u32 $D2,$H4#hi,${S3}[1] + + vmlal.u32 $D3,$H4#hi,${S4}[1] + vmlal.u32 $D0,$H1#hi,${S4}[1] + vmlal.u32 $D4,$H0#hi,${R4}[1] + vmlal.u32 $D1,$H2#hi,${S4}[1] + vmlal.u32 $D2,$H3#hi,${S4}[1] + + vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0) + add $in2,$in2,#64 + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ (hash+inp[0:1])*r^4 and accumulate + + vmlal.u32 $D3,$H3#lo,${R0}[0] + vmlal.u32 $D0,$H0#lo,${R0}[0] + vmlal.u32 $D4,$H4#lo,${R0}[0] + vmlal.u32 $D1,$H1#lo,${R0}[0] + vmlal.u32 $D2,$H2#lo,${R0}[0] + vld1.32 ${S4}[0],[$tbl0,:32] + + vmlal.u32 $D3,$H2#lo,${R1}[0] + vmlal.u32 $D0,$H4#lo,${S1}[0] + vmlal.u32 $D4,$H3#lo,${R1}[0] + vmlal.u32 $D1,$H0#lo,${R1}[0] + vmlal.u32 $D2,$H1#lo,${R1}[0] + + vmlal.u32 $D3,$H1#lo,${R2}[0] + vmlal.u32 $D0,$H3#lo,${S2}[0] + vmlal.u32 $D4,$H2#lo,${R2}[0] + vmlal.u32 $D1,$H4#lo,${S2}[0] + vmlal.u32 $D2,$H0#lo,${R2}[0] + + vmlal.u32 $D3,$H0#lo,${R3}[0] + vmlal.u32 $D0,$H2#lo,${S3}[0] + vmlal.u32 $D4,$H1#lo,${R3}[0] + vmlal.u32 $D1,$H3#lo,${S3}[0] + vmlal.u32 $D3,$H4#lo,${S4}[0] + + vmlal.u32 $D2,$H4#lo,${S3}[0] + vmlal.u32 $D0,$H1#lo,${S4}[0] + vmlal.u32 $D4,$H0#lo,${R4}[0] + vmov.i32 $H4,#1<<24 @ padbit, yes, always + vmlal.u32 $D1,$H2#lo,${S4}[0] + vmlal.u32 $D2,$H3#lo,${S4}[0] + + vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1] + add $inp,$inp,#64 +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 + vrev32.8 $H3,$H3 +# endif + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction interleaved with base 2^32 -> base 2^26 + + vshr.u64 $T0,$D3,#26 + vmovn.i64 $D3#lo,$D3 + vshr.u64 $T1,$D0,#26 + vmovn.i64 $D0#lo,$D0 + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vbic.i32 $D3#lo,#0xfc000000 + vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26 + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + vshl.u32 $H3,$H3,#18 + vbic.i32 $D0#lo,#0xfc000000 + + vshrn.u64 $T0#lo,$D4,#26 + vmovn.i64 $D4#lo,$D4 + vshr.u64 $T1,$D1,#26 + vmovn.i64 $D1#lo,$D1 + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + vsri.u32 $H3,$H2,#14 + vbic.i32 $D4#lo,#0xfc000000 + vshl.u32 $H2,$H2,#12 + vbic.i32 $D1#lo,#0xfc000000 + + vadd.i32 $D0#lo,$D0#lo,$T0#lo + vshl.u32 $T0#lo,$T0#lo,#2 + vbic.i32 $H3,#0xfc000000 + vshrn.u64 $T1#lo,$D2,#26 + vmovn.i64 $D2#lo,$D2 + vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0 + vsri.u32 $H2,$H1,#20 + vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3 + vshl.u32 $H1,$H1,#6 + vbic.i32 $D2#lo,#0xfc000000 + vbic.i32 $H2,#0xfc000000 + + vshr.u32 $T0#lo,$D0#lo,#26 + vbic.i32 $D0#lo,#0xfc000000 + vsri.u32 $H1,$H0,#26 + vbic.i32 $H0,#0xfc000000 + vshr.u32 $T1#lo,$D3#lo,#26 + vbic.i32 $D3#lo,#0xfc000000 + vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1 + vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4 + vbic.i32 $H1,#0xfc000000 + + bhi .Loop_neon + +.Lskip_loop: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + add $tbl1,$ctx,#(48+0*9*4) + add $tbl0,$ctx,#(48+1*9*4) + adds $len,$len,#32 +# ifdef __thumb2__ + it ne +# endif + movne $len,#0 + bne .Long_tail + + vadd.i32 $H2#hi,$H2#lo,$D2#lo @ add hash value and move to #hi + vadd.i32 $H0#hi,$H0#lo,$D0#lo + vadd.i32 $H3#hi,$H3#lo,$D3#lo + vadd.i32 $H1#hi,$H1#lo,$D1#lo + vadd.i32 $H4#hi,$H4#lo,$D4#lo + +.Long_tail: + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^1 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^2 + + vadd.i32 $H2#lo,$H2#lo,$D2#lo @ can be redundant + vmull.u32 $D2,$H2#hi,$R0 + vadd.i32 $H0#lo,$H0#lo,$D0#lo + vmull.u32 $D0,$H0#hi,$R0 + vadd.i32 $H3#lo,$H3#lo,$D3#lo + vmull.u32 $D3,$H3#hi,$R0 + vadd.i32 $H1#lo,$H1#lo,$D1#lo + vmull.u32 $D1,$H1#hi,$R0 + vadd.i32 $H4#lo,$H4#lo,$D4#lo + vmull.u32 $D4,$H4#hi,$R0 + + vmlal.u32 $D0,$H4#hi,$S1 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vmlal.u32 $D3,$H2#hi,$R1 + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vmlal.u32 $D1,$H0#hi,$R1 + vmlal.u32 $D4,$H3#hi,$R1 + vmlal.u32 $D2,$H1#hi,$R1 + + vmlal.u32 $D3,$H1#hi,$R2 + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D0,$H3#hi,$S2 + vld1.32 ${S4}[0],[$tbl0,:32] + vmlal.u32 $D4,$H2#hi,$R2 + vmlal.u32 $D1,$H4#hi,$S2 + vmlal.u32 $D2,$H0#hi,$R2 + + vmlal.u32 $D3,$H0#hi,$R3 +# ifdef __thumb2__ + it ne +# endif + addne $tbl1,$ctx,#(48+2*9*4) + vmlal.u32 $D0,$H2#hi,$S3 +# ifdef __thumb2__ + it ne +# endif + addne $tbl0,$ctx,#(48+3*9*4) + vmlal.u32 $D4,$H1#hi,$R3 + vmlal.u32 $D1,$H3#hi,$S3 + vmlal.u32 $D2,$H4#hi,$S3 + + vmlal.u32 $D3,$H4#hi,$S4 + vorn $MASK,$MASK,$MASK @ all-ones, can be redundant + vmlal.u32 $D0,$H1#hi,$S4 + vshr.u64 $MASK,$MASK,#38 + vmlal.u32 $D4,$H0#hi,$R4 + vmlal.u32 $D1,$H2#hi,$S4 + vmlal.u32 $D2,$H3#hi,$S4 + + beq .Lshort_tail + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ (hash+inp[0:1])*r^4:r^3 and accumulate + + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^3 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4 + + vmlal.u32 $D2,$H2#lo,$R0 + vmlal.u32 $D0,$H0#lo,$R0 + vmlal.u32 $D3,$H3#lo,$R0 + vmlal.u32 $D1,$H1#lo,$R0 + vmlal.u32 $D4,$H4#lo,$R0 + + vmlal.u32 $D0,$H4#lo,$S1 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vmlal.u32 $D3,$H2#lo,$R1 + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vmlal.u32 $D1,$H0#lo,$R1 + vmlal.u32 $D4,$H3#lo,$R1 + vmlal.u32 $D2,$H1#lo,$R1 + + vmlal.u32 $D3,$H1#lo,$R2 + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D0,$H3#lo,$S2 + vld1.32 ${S4}[0],[$tbl0,:32] + vmlal.u32 $D4,$H2#lo,$R2 + vmlal.u32 $D1,$H4#lo,$S2 + vmlal.u32 $D2,$H0#lo,$R2 + + vmlal.u32 $D3,$H0#lo,$R3 + vmlal.u32 $D0,$H2#lo,$S3 + vmlal.u32 $D4,$H1#lo,$R3 + vmlal.u32 $D1,$H3#lo,$S3 + vmlal.u32 $D2,$H4#lo,$S3 + + vmlal.u32 $D3,$H4#lo,$S4 + vorn $MASK,$MASK,$MASK @ all-ones + vmlal.u32 $D0,$H1#lo,$S4 + vshr.u64 $MASK,$MASK,#38 + vmlal.u32 $D4,$H0#lo,$R4 + vmlal.u32 $D1,$H2#lo,$S4 + vmlal.u32 $D2,$H3#lo,$S4 + +.Lshort_tail: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ horizontal addition + + vadd.i64 $D3#lo,$D3#lo,$D3#hi + vadd.i64 $D0#lo,$D0#lo,$D0#hi + vadd.i64 $D4#lo,$D4#lo,$D4#hi + vadd.i64 $D1#lo,$D1#lo,$D1#hi + vadd.i64 $D2#lo,$D2#lo,$D2#hi + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction, but without narrowing + + vshr.u64 $T0,$D3,#26 + vand.i64 $D3,$D3,$MASK + vshr.u64 $T1,$D0,#26 + vand.i64 $D0,$D0,$MASK + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + + vshr.u64 $T0,$D4,#26 + vand.i64 $D4,$D4,$MASK + vshr.u64 $T1,$D1,#26 + vand.i64 $D1,$D1,$MASK + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + + vadd.i64 $D0,$D0,$T0 + vshl.u64 $T0,$T0,#2 + vshr.u64 $T1,$D2,#26 + vand.i64 $D2,$D2,$MASK + vadd.i64 $D0,$D0,$T0 @ h4 -> h0 + vadd.i64 $D3,$D3,$T1 @ h2 -> h3 + + vshr.u64 $T0,$D0,#26 + vand.i64 $D0,$D0,$MASK + vshr.u64 $T1,$D3,#26 + vand.i64 $D3,$D3,$MASK + vadd.i64 $D1,$D1,$T0 @ h0 -> h1 + vadd.i64 $D4,$D4,$T1 @ h3 -> h4 + + cmp $len,#0 + bne .Leven + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ store hash value + + vst4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]! + vst1.32 {$D4#lo[0]},[$ctx] + + vldmia sp!,{d8-d15} @ epilogue + ldmia sp!,{r4-r7} +.Lno_data_neon: + ret @ bx lr +.size poly1305_blocks_neon,.-poly1305_blocks_neon + +.type poly1305_emit_neon,%function +.align 5 +poly1305_emit_neon: + ldr ip,[$ctx,#36] @ is_base2_26 + + stmdb sp!,{r4-r11} + + tst ip,ip + beq .Lpoly1305_emit_enter + + ldmia $ctx,{$h0-$h4} + eor $g0,$g0,$g0 + + adds $h0,$h0,$h1,lsl#26 @ base 2^26 -> base 2^32 + mov $h1,$h1,lsr#6 + adcs $h1,$h1,$h2,lsl#20 + mov $h2,$h2,lsr#12 + adcs $h2,$h2,$h3,lsl#14 + mov $h3,$h3,lsr#18 + adcs $h3,$h3,$h4,lsl#8 + adc $h4,$g0,$h4,lsr#24 @ can be partially reduced ... + + and $g0,$h4,#-4 @ ... so reduce + and $h4,$h3,#3 + add $g0,$g0,$g0,lsr#2 @ *= 5 + adds $h0,$h0,$g0 + adcs $h1,$h1,#0 + adcs $h2,$h2,#0 + adc $h3,$h3,#0 + + adds $g0,$h0,#5 @ compare to modulus + adcs $g1,$h1,#0 + adcs $g2,$h2,#0 + adcs $g3,$h3,#0 + adc $g4,$h4,#0 + tst $g4,#4 @ did it carry/borrow? + +# ifdef __thumb2__ + it ne +# endif + movne $h0,$g0 + ldr $g0,[$nonce,#0] +# ifdef __thumb2__ + it ne +# endif + movne $h1,$g1 + ldr $g1,[$nonce,#4] +# ifdef __thumb2__ + it ne +# endif + movne $h2,$g2 + ldr $g2,[$nonce,#8] +# ifdef __thumb2__ + it ne +# endif + movne $h3,$g3 + ldr $g3,[$nonce,#12] + + adds $h0,$h0,$g0 @ accumulate nonce + adcs $h1,$h1,$g1 + adcs $h2,$h2,$g2 + adc $h3,$h3,$g3 + +# ifdef __ARMEB__ + rev $h0,$h0 + rev $h1,$h1 + rev $h2,$h2 + rev $h3,$h3 +# endif + str $h0,[$mac,#0] @ store the result + str $h1,[$mac,#4] + str $h2,[$mac,#8] + str $h3,[$mac,#12] + + ldmia sp!,{r4-r11} + ret @ bx lr +.size poly1305_emit_neon,.-poly1305_emit_neon + +.align 5 +.Lzeros: +.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lpoly1305_init +#endif +___ +} } +$code.=<<___; +.asciz "Poly1305 for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +#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/\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/external/boringssl/crypto/poly1305/asm/poly1305-armv8.pl b/external/boringssl/crypto/poly1305/asm/poly1305-armv8.pl new file mode 100755 index 0000000000..1d9a81b8b0 --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-armv8.pl @@ -0,0 +1,925 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 Poly1305 hash for ARMv8. +# +# June 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone. +# +# IALU/gcc-4.9 NEON +# +# Apple A7 1.86/+5% 0.72 +# Cortex-A53 2.63/+58% 1.47 +# Cortex-A57 2.70/+7% 1.14 +# Denver 1.39/+50% 1.18(*) +# X-Gene 2.00/+68% 2.19 +# +# (*) estimate based on resources availability is less than 1.0, +# i.e. measured result is worse than expected, presumably binary +# translator is not almighty; + +$flavour=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my ($ctx,$inp,$len,$padbit) = map("x$_",(0..3)); +my ($mac,$nonce)=($inp,$len); + +my ($h0,$h1,$h2,$r0,$r1,$s1,$t0,$t1,$d0,$d1,$d2) = map("x$_",(4..14)); + +$code.=<<___; +#include + +.text + +// forward "declarations" are required for Apple +.extern OPENSSL_armcap_P +.globl poly1305_blocks +.globl poly1305_emit + +.globl poly1305_init +.type poly1305_init,%function +.align 5 +poly1305_init: + cmp $inp,xzr + stp xzr,xzr,[$ctx] // zero hash value + stp xzr,xzr,[$ctx,#16] // [along with is_base2_26] + + csel x0,xzr,x0,eq + b.eq .Lno_key + +#ifdef __ILP32__ + ldrsw $t1,.LOPENSSL_armcap_P +#else + ldr $t1,.LOPENSSL_armcap_P +#endif + adr $t0,.LOPENSSL_armcap_P + + ldp $r0,$r1,[$inp] // load key + mov $s1,#0xfffffffc0fffffff + movk $s1,#0x0fff,lsl#48 + ldr w17,[$t0,$t1] +#ifdef __ARMEB__ + rev $r0,$r0 // flip bytes + rev $r1,$r1 +#endif + and $r0,$r0,$s1 // &=0ffffffc0fffffff + and $s1,$s1,#-4 + and $r1,$r1,$s1 // &=0ffffffc0ffffffc + stp $r0,$r1,[$ctx,#32] // save key value + + tst w17,#ARMV7_NEON + + adr $d0,poly1305_blocks + adr $r0,poly1305_blocks_neon + adr $d1,poly1305_emit + adr $r1,poly1305_emit_neon + + csel $d0,$d0,$r0,eq + csel $d1,$d1,$r1,eq + + stp $d0,$d1,[$len] + + mov x0,#1 +.Lno_key: + ret +.size poly1305_init,.-poly1305_init + +.type poly1305_blocks,%function +.align 5 +poly1305_blocks: + ands $len,$len,#-16 + b.eq .Lno_data + + ldp $h0,$h1,[$ctx] // load hash value + ldp $r0,$r1,[$ctx,#32] // load key value + ldr $h2,[$ctx,#16] + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + b .Loop + +.align 5 +.Loop: + ldp $t0,$t1,[$inp],#16 // load input + sub $len,$len,#16 +#ifdef __ARMEB__ + rev $t0,$t0 + rev $t1,$t1 +#endif + adds $h0,$h0,$t0 // accumulate input + adcs $h1,$h1,$t1 + + mul $d0,$h0,$r0 // h0*r0 + adc $h2,$h2,$padbit + umulh $d1,$h0,$r0 + + mul $t0,$h1,$s1 // h1*5*r1 + umulh $t1,$h1,$s1 + + adds $d0,$d0,$t0 + mul $t0,$h0,$r1 // h0*r1 + adc $d1,$d1,$t1 + umulh $d2,$h0,$r1 + + adds $d1,$d1,$t0 + mul $t0,$h1,$r0 // h1*r0 + adc $d2,$d2,xzr + umulh $t1,$h1,$r0 + + adds $d1,$d1,$t0 + mul $t0,$h2,$s1 // h2*5*r1 + adc $d2,$d2,$t1 + mul $t1,$h2,$r0 // h2*r0 + + adds $d1,$d1,$t0 + adc $d2,$d2,$t1 + + and $t0,$d2,#-4 // final reduction + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$d0,$t0 + adc $h1,$d1,xzr + + cbnz $len,.Loop + + stp $h0,$h1,[$ctx] // store hash value + str $h2,[$ctx,#16] + +.Lno_data: + ret +.size poly1305_blocks,.-poly1305_blocks + +.type poly1305_emit,%function +.align 5 +poly1305_emit: + ldp $h0,$h1,[$ctx] // load hash base 2^64 + ldr $h2,[$ctx,#16] + ldp $t0,$t1,[$nonce] // load nonce + + adds $d0,$h0,#5 // compare to modulus + adcs $d1,$h1,xzr + adc $d2,$h2,xzr + + tst $d2,#-4 // see if it's carried/borrowed + + csel $h0,$h0,$d0,eq + csel $h1,$h1,$d1,eq + +#ifdef __ARMEB__ + ror $t0,$t0,#32 // flip nonce words + ror $t1,$t1,#32 +#endif + adds $h0,$h0,$t0 // accumulate nonce + adc $h1,$h1,$t1 +#ifdef __ARMEB__ + rev $h0,$h0 // flip output bytes + rev $h1,$h1 +#endif + stp $h0,$h1,[$mac] // write result + + ret +.size poly1305_emit,.-poly1305_emit +___ +my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("v$_.4s",(0..8)); +my ($IN01_0,$IN01_1,$IN01_2,$IN01_3,$IN01_4) = map("v$_.2s",(9..13)); +my ($IN23_0,$IN23_1,$IN23_2,$IN23_3,$IN23_4) = map("v$_.2s",(14..18)); +my ($ACC0,$ACC1,$ACC2,$ACC3,$ACC4) = map("v$_.2d",(19..23)); +my ($H0,$H1,$H2,$H3,$H4) = map("v$_.2s",(24..28)); +my ($T0,$T1,$MASK) = map("v$_",(29..31)); + +my ($in2,$zeros)=("x16","x17"); +my $is_base2_26 = $zeros; # borrow + +$code.=<<___; +.type poly1305_mult,%function +.align 5 +poly1305_mult: + mul $d0,$h0,$r0 // h0*r0 + umulh $d1,$h0,$r0 + + mul $t0,$h1,$s1 // h1*5*r1 + umulh $t1,$h1,$s1 + + adds $d0,$d0,$t0 + mul $t0,$h0,$r1 // h0*r1 + adc $d1,$d1,$t1 + umulh $d2,$h0,$r1 + + adds $d1,$d1,$t0 + mul $t0,$h1,$r0 // h1*r0 + adc $d2,$d2,xzr + umulh $t1,$h1,$r0 + + adds $d1,$d1,$t0 + mul $t0,$h2,$s1 // h2*5*r1 + adc $d2,$d2,$t1 + mul $t1,$h2,$r0 // h2*r0 + + adds $d1,$d1,$t0 + adc $d2,$d2,$t1 + + and $t0,$d2,#-4 // final reduction + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$d0,$t0 + adc $h1,$d1,xzr + + ret +.size poly1305_mult,.-poly1305_mult + +.type poly1305_splat,%function +.align 5 +poly1305_splat: + and x12,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x13,$h0,#26,#26 + extr x14,$h1,$h0,#52 + and x14,x14,#0x03ffffff + ubfx x15,$h1,#14,#26 + extr x16,$h2,$h1,#40 + + str w12,[$ctx,#16*0] // r0 + add w12,w13,w13,lsl#2 // r1*5 + str w13,[$ctx,#16*1] // r1 + add w13,w14,w14,lsl#2 // r2*5 + str w12,[$ctx,#16*2] // s1 + str w14,[$ctx,#16*3] // r2 + add w14,w15,w15,lsl#2 // r3*5 + str w13,[$ctx,#16*4] // s2 + str w15,[$ctx,#16*5] // r3 + add w15,w16,w16,lsl#2 // r4*5 + str w14,[$ctx,#16*6] // s3 + str w16,[$ctx,#16*7] // r4 + str w15,[$ctx,#16*8] // s4 + + ret +.size poly1305_splat,.-poly1305_splat + +.type poly1305_blocks_neon,%function +.align 5 +poly1305_blocks_neon: + ldr $is_base2_26,[$ctx,#24] + cmp $len,#128 + b.hs .Lblocks_neon + cbz $is_base2_26,poly1305_blocks + +.Lblocks_neon: + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + + ands $len,$len,#-16 + b.eq .Lno_data_neon + + cbz $is_base2_26,.Lbase2_64_neon + + ldp w10,w11,[$ctx] // load hash value base 2^26 + ldp w12,w13,[$ctx,#8] + ldr w14,[$ctx,#16] + + tst $len,#31 + b.eq .Leven_neon + + ldp $r0,$r1,[$ctx,#32] // load key value + + add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64 + lsr $h1,x12,#12 + adds $h0,$h0,x12,lsl#52 + add $h1,$h1,x13,lsl#14 + adc $h1,$h1,xzr + lsr $h2,x14,#24 + adds $h1,$h1,x14,lsl#40 + adc $d2,$h2,xzr // can be partially reduced... + + ldp $d0,$d1,[$inp],#16 // load input + sub $len,$len,#16 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + + and $t0,$d2,#-4 // ... so reduce + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$h0,$t0 + adc $h1,$h1,xzr + +#ifdef __ARMEB__ + rev $d0,$d0 + rev $d1,$d1 +#endif + adds $h0,$h0,$d0 // accumulate input + adcs $h1,$h1,$d1 + adc $h2,$h2,$padbit + + bl poly1305_mult + ldr x30,[sp,#8] + + cbz $padbit,.Lstore_base2_64_neon + + and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x11,$h0,#26,#26 + extr x12,$h1,$h0,#52 + and x12,x12,#0x03ffffff + ubfx x13,$h1,#14,#26 + extr x14,$h2,$h1,#40 + + cbnz $len,.Leven_neon + + stp w10,w11,[$ctx] // store hash value base 2^26 + stp w12,w13,[$ctx,#8] + str w14,[$ctx,#16] + b .Lno_data_neon + +.align 4 +.Lstore_base2_64_neon: + stp $h0,$h1,[$ctx] // store hash value base 2^64 + stp $h2,xzr,[$ctx,#16] // note that is_base2_26 is zeroed + b .Lno_data_neon + +.align 4 +.Lbase2_64_neon: + ldp $r0,$r1,[$ctx,#32] // load key value + + ldp $h0,$h1,[$ctx] // load hash value base 2^64 + ldr $h2,[$ctx,#16] + + tst $len,#31 + b.eq .Linit_neon + + ldp $d0,$d1,[$inp],#16 // load input + sub $len,$len,#16 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) +#ifdef __ARMEB__ + rev $d0,$d0 + rev $d1,$d1 +#endif + adds $h0,$h0,$d0 // accumulate input + adcs $h1,$h1,$d1 + adc $h2,$h2,$padbit + + bl poly1305_mult + +.Linit_neon: + and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x11,$h0,#26,#26 + extr x12,$h1,$h0,#52 + and x12,x12,#0x03ffffff + ubfx x13,$h1,#14,#26 + extr x14,$h2,$h1,#40 + + stp d8,d9,[sp,#16] // meet ABI requirements + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] + + fmov ${H0},x10 + fmov ${H1},x11 + fmov ${H2},x12 + fmov ${H3},x13 + fmov ${H4},x14 + + ////////////////////////////////// initialize r^n table + mov $h0,$r0 // r^1 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + mov $h1,$r1 + mov $h2,xzr + add $ctx,$ctx,#48+12 + bl poly1305_splat + + bl poly1305_mult // r^2 + sub $ctx,$ctx,#4 + bl poly1305_splat + + bl poly1305_mult // r^3 + sub $ctx,$ctx,#4 + bl poly1305_splat + + bl poly1305_mult // r^4 + sub $ctx,$ctx,#4 + bl poly1305_splat + ldr x30,[sp,#8] + + add $in2,$inp,#32 + adr $zeros,.Lzeros + subs $len,$len,#64 + csel $in2,$zeros,$in2,lo + + mov x4,#1 + str x4,[$ctx,#-24] // set is_base2_26 + sub $ctx,$ctx,#48 // restore original $ctx + b .Ldo_neon + +.align 4 +.Leven_neon: + add $in2,$inp,#32 + adr $zeros,.Lzeros + subs $len,$len,#64 + csel $in2,$zeros,$in2,lo + + stp d8,d9,[sp,#16] // meet ABI requirements + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] + + fmov ${H0},x10 + fmov ${H1},x11 + fmov ${H2},x12 + fmov ${H3},x13 + fmov ${H4},x14 + +.Ldo_neon: + ldp x8,x12,[$in2],#16 // inp[2:3] (or zero) + ldp x9,x13,[$in2],#48 + + lsl $padbit,$padbit,#24 + add x15,$ctx,#48 + +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + and x5,x9,#0x03ffffff + ubfx x6,x8,#26,#26 + ubfx x7,x9,#26,#26 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + extr x8,x12,x8,#52 + extr x9,x13,x9,#52 + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + fmov $IN23_0,x4 + and x8,x8,#0x03ffffff + and x9,x9,#0x03ffffff + ubfx x10,x12,#14,#26 + ubfx x11,x13,#14,#26 + add x12,$padbit,x12,lsr#40 + add x13,$padbit,x13,lsr#40 + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + fmov $IN23_1,x6 + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + fmov $IN23_2,x8 + fmov $IN23_3,x10 + fmov $IN23_4,x12 + + ldp x8,x12,[$inp],#16 // inp[0:1] + ldp x9,x13,[$inp],#48 + + ld1 {$R0,$R1,$S1,$R2},[x15],#64 + ld1 {$S2,$R3,$S3,$R4},[x15],#64 + ld1 {$S4},[x15] + +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + and x5,x9,#0x03ffffff + ubfx x6,x8,#26,#26 + ubfx x7,x9,#26,#26 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + extr x8,x12,x8,#52 + extr x9,x13,x9,#52 + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + fmov $IN01_0,x4 + and x8,x8,#0x03ffffff + and x9,x9,#0x03ffffff + ubfx x10,x12,#14,#26 + ubfx x11,x13,#14,#26 + add x12,$padbit,x12,lsr#40 + add x13,$padbit,x13,lsr#40 + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + fmov $IN01_1,x6 + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + fmov $IN01_2,x8 + fmov $IN01_3,x10 + fmov $IN01_4,x12 + + b.ls .Lskip_loop + +.align 4 +.Loop_neon: + //////////////////////////////////////////////////////////////// + // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + // \___________________/ + // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + // \___________________/ \____________________/ + // + // Note that we start with inp[2:3]*r^2. This is because it + // doesn't depend on reduction in previous iteration. + //////////////////////////////////////////////////////////////// + // d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0 + // d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*5*r4 + // d2 = h0*r2 + h1*r1 + h2*r0 + h3*5*r4 + h4*5*r3 + // d1 = h0*r1 + h1*r0 + h2*5*r4 + h3*5*r3 + h4*5*r2 + // d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + subs $len,$len,#64 + umull $ACC4,$IN23_0,${R4}[2] + csel $in2,$zeros,$in2,lo + umull $ACC3,$IN23_0,${R3}[2] + umull $ACC2,$IN23_0,${R2}[2] + ldp x8,x12,[$in2],#16 // inp[2:3] (or zero) + umull $ACC1,$IN23_0,${R1}[2] + ldp x9,x13,[$in2],#48 + umull $ACC0,$IN23_0,${R0}[2] +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + + umlal $ACC4,$IN23_1,${R3}[2] + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + umlal $ACC3,$IN23_1,${R2}[2] + and x5,x9,#0x03ffffff + umlal $ACC2,$IN23_1,${R1}[2] + ubfx x6,x8,#26,#26 + umlal $ACC1,$IN23_1,${R0}[2] + ubfx x7,x9,#26,#26 + umlal $ACC0,$IN23_1,${S4}[2] + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + + umlal $ACC4,$IN23_2,${R2}[2] + extr x8,x12,x8,#52 + umlal $ACC3,$IN23_2,${R1}[2] + extr x9,x13,x9,#52 + umlal $ACC2,$IN23_2,${R0}[2] + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + umlal $ACC1,$IN23_2,${S4}[2] + fmov $IN23_0,x4 + umlal $ACC0,$IN23_2,${S3}[2] + and x8,x8,#0x03ffffff + + umlal $ACC4,$IN23_3,${R1}[2] + and x9,x9,#0x03ffffff + umlal $ACC3,$IN23_3,${R0}[2] + ubfx x10,x12,#14,#26 + umlal $ACC2,$IN23_3,${S4}[2] + ubfx x11,x13,#14,#26 + umlal $ACC1,$IN23_3,${S3}[2] + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + umlal $ACC0,$IN23_3,${S2}[2] + fmov $IN23_1,x6 + + add $IN01_2,$IN01_2,$H2 + add x12,$padbit,x12,lsr#40 + umlal $ACC4,$IN23_4,${R0}[2] + add x13,$padbit,x13,lsr#40 + umlal $ACC3,$IN23_4,${S4}[2] + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + umlal $ACC2,$IN23_4,${S3}[2] + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + umlal $ACC1,$IN23_4,${S2}[2] + fmov $IN23_2,x8 + umlal $ACC0,$IN23_4,${S1}[2] + fmov $IN23_3,x10 + + //////////////////////////////////////////////////////////////// + // (hash+inp[0:1])*r^4 and accumulate + + add $IN01_0,$IN01_0,$H0 + fmov $IN23_4,x12 + umlal $ACC3,$IN01_2,${R1}[0] + ldp x8,x12,[$inp],#16 // inp[0:1] + umlal $ACC0,$IN01_2,${S3}[0] + ldp x9,x13,[$inp],#48 + umlal $ACC4,$IN01_2,${R2}[0] + umlal $ACC1,$IN01_2,${S4}[0] + umlal $ACC2,$IN01_2,${R0}[0] +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + + add $IN01_1,$IN01_1,$H1 + umlal $ACC3,$IN01_0,${R3}[0] + umlal $ACC4,$IN01_0,${R4}[0] + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + umlal $ACC2,$IN01_0,${R2}[0] + and x5,x9,#0x03ffffff + umlal $ACC0,$IN01_0,${R0}[0] + ubfx x6,x8,#26,#26 + umlal $ACC1,$IN01_0,${R1}[0] + ubfx x7,x9,#26,#26 + + add $IN01_3,$IN01_3,$H3 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + umlal $ACC3,$IN01_1,${R2}[0] + extr x8,x12,x8,#52 + umlal $ACC4,$IN01_1,${R3}[0] + extr x9,x13,x9,#52 + umlal $ACC0,$IN01_1,${S4}[0] + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + umlal $ACC2,$IN01_1,${R1}[0] + fmov $IN01_0,x4 + umlal $ACC1,$IN01_1,${R0}[0] + and x8,x8,#0x03ffffff + + add $IN01_4,$IN01_4,$H4 + and x9,x9,#0x03ffffff + umlal $ACC3,$IN01_3,${R0}[0] + ubfx x10,x12,#14,#26 + umlal $ACC0,$IN01_3,${S2}[0] + ubfx x11,x13,#14,#26 + umlal $ACC4,$IN01_3,${R1}[0] + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + umlal $ACC1,$IN01_3,${S3}[0] + fmov $IN01_1,x6 + umlal $ACC2,$IN01_3,${S4}[0] + add x12,$padbit,x12,lsr#40 + + umlal $ACC3,$IN01_4,${S4}[0] + add x13,$padbit,x13,lsr#40 + umlal $ACC0,$IN01_4,${S1}[0] + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + umlal $ACC4,$IN01_4,${R0}[0] + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + umlal $ACC1,$IN01_4,${S2}[0] + fmov $IN01_2,x8 + umlal $ACC2,$IN01_4,${S3}[0] + fmov $IN01_3,x10 + + ///////////////////////////////////////////////////////////////// + // lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + // and P. Schwabe + + ushr $T0.2d,$ACC3,#26 + fmov $IN01_4,x12 + xtn $H3,$ACC3 + ushr $T1.2d,$ACC0,#26 + xtn $H0,$ACC0 + add $ACC4,$ACC4,$T0.2d // h3 -> h4 + bic $H3,#0xfc,lsl#24 // &=0x03ffffff + add $ACC1,$ACC1,$T1.2d // h0 -> h1 + bic $H0,#0xfc,lsl#24 + + shrn $T0.2s,$ACC4,#26 + xtn $H4,$ACC4 + ushr $T1.2d,$ACC1,#26 + xtn $H1,$ACC1 + add $ACC2,$ACC2,$T1.2d // h1 -> h2 + bic $H4,#0xfc,lsl#24 + bic $H1,#0xfc,lsl#24 + + add $H0,$H0,$T0.2s + shl $T0.2s,$T0.2s,#2 + shrn $T1.2s,$ACC2,#26 + xtn $H2,$ACC2 + add $H0,$H0,$T0.2s // h4 -> h0 + add $H3,$H3,$T1.2s // h2 -> h3 + bic $H2,#0xfc,lsl#24 + + ushr $T0.2s,$H0,#26 + bic $H0,#0xfc,lsl#24 + ushr $T1.2s,$H3,#26 + bic $H3,#0xfc,lsl#24 + add $H1,$H1,$T0.2s // h0 -> h1 + add $H4,$H4,$T1.2s // h3 -> h4 + + b.hi .Loop_neon + +.Lskip_loop: + dup $IN23_2,${IN23_2}[0] + movi $MASK.2d,#-1 + add $IN01_2,$IN01_2,$H2 + ushr $MASK.2d,$MASK.2d,#38 + + //////////////////////////////////////////////////////////////// + // multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + adds $len,$len,#32 + b.ne .Long_tail + + dup $IN23_2,${IN01_2}[0] + add $IN23_0,$IN01_0,$H0 + add $IN23_3,$IN01_3,$H3 + add $IN23_1,$IN01_1,$H1 + add $IN23_4,$IN01_4,$H4 + +.Long_tail: + dup $IN23_0,${IN23_0}[0] + umull2 $ACC0,$IN23_2,${S3} + umull2 $ACC3,$IN23_2,${R1} + umull2 $ACC4,$IN23_2,${R2} + umull2 $ACC2,$IN23_2,${R0} + umull2 $ACC1,$IN23_2,${S4} + + dup $IN23_1,${IN23_1}[0] + umlal2 $ACC0,$IN23_0,${R0} + umlal2 $ACC2,$IN23_0,${R2} + umlal2 $ACC3,$IN23_0,${R3} + umlal2 $ACC4,$IN23_0,${R4} + umlal2 $ACC1,$IN23_0,${R1} + + dup $IN23_3,${IN23_3}[0] + umlal2 $ACC0,$IN23_1,${S4} + umlal2 $ACC3,$IN23_1,${R2} + umlal2 $ACC2,$IN23_1,${R1} + umlal2 $ACC4,$IN23_1,${R3} + umlal2 $ACC1,$IN23_1,${R0} + + dup $IN23_4,${IN23_4}[0] + umlal2 $ACC3,$IN23_3,${R0} + umlal2 $ACC4,$IN23_3,${R1} + umlal2 $ACC0,$IN23_3,${S2} + umlal2 $ACC1,$IN23_3,${S3} + umlal2 $ACC2,$IN23_3,${S4} + + umlal2 $ACC3,$IN23_4,${S4} + umlal2 $ACC0,$IN23_4,${S1} + umlal2 $ACC4,$IN23_4,${R0} + umlal2 $ACC1,$IN23_4,${S2} + umlal2 $ACC2,$IN23_4,${S3} + + b.eq .Lshort_tail + + //////////////////////////////////////////////////////////////// + // (hash+inp[0:1])*r^4:r^3 and accumulate + + add $IN01_0,$IN01_0,$H0 + umlal $ACC3,$IN01_2,${R1} + umlal $ACC0,$IN01_2,${S3} + umlal $ACC4,$IN01_2,${R2} + umlal $ACC1,$IN01_2,${S4} + umlal $ACC2,$IN01_2,${R0} + + add $IN01_1,$IN01_1,$H1 + umlal $ACC3,$IN01_0,${R3} + umlal $ACC0,$IN01_0,${R0} + umlal $ACC4,$IN01_0,${R4} + umlal $ACC1,$IN01_0,${R1} + umlal $ACC2,$IN01_0,${R2} + + add $IN01_3,$IN01_3,$H3 + umlal $ACC3,$IN01_1,${R2} + umlal $ACC0,$IN01_1,${S4} + umlal $ACC4,$IN01_1,${R3} + umlal $ACC1,$IN01_1,${R0} + umlal $ACC2,$IN01_1,${R1} + + add $IN01_4,$IN01_4,$H4 + umlal $ACC3,$IN01_3,${R0} + umlal $ACC0,$IN01_3,${S2} + umlal $ACC4,$IN01_3,${R1} + umlal $ACC1,$IN01_3,${S3} + umlal $ACC2,$IN01_3,${S4} + + umlal $ACC3,$IN01_4,${S4} + umlal $ACC0,$IN01_4,${S1} + umlal $ACC4,$IN01_4,${R0} + umlal $ACC1,$IN01_4,${S2} + umlal $ACC2,$IN01_4,${S3} + +.Lshort_tail: + //////////////////////////////////////////////////////////////// + // horizontal add + + addp $ACC3,$ACC3,$ACC3 + ldp d8,d9,[sp,#16] // meet ABI requirements + addp $ACC0,$ACC0,$ACC0 + ldp d10,d11,[sp,#32] + addp $ACC4,$ACC4,$ACC4 + ldp d12,d13,[sp,#48] + addp $ACC1,$ACC1,$ACC1 + ldp d14,d15,[sp,#64] + addp $ACC2,$ACC2,$ACC2 + + //////////////////////////////////////////////////////////////// + // lazy reduction, but without narrowing + + ushr $T0.2d,$ACC3,#26 + and $ACC3,$ACC3,$MASK.2d + ushr $T1.2d,$ACC0,#26 + and $ACC0,$ACC0,$MASK.2d + + add $ACC4,$ACC4,$T0.2d // h3 -> h4 + add $ACC1,$ACC1,$T1.2d // h0 -> h1 + + ushr $T0.2d,$ACC4,#26 + and $ACC4,$ACC4,$MASK.2d + ushr $T1.2d,$ACC1,#26 + and $ACC1,$ACC1,$MASK.2d + add $ACC2,$ACC2,$T1.2d // h1 -> h2 + + add $ACC0,$ACC0,$T0.2d + shl $T0.2d,$T0.2d,#2 + ushr $T1.2d,$ACC2,#26 + and $ACC2,$ACC2,$MASK.2d + add $ACC0,$ACC0,$T0.2d // h4 -> h0 + add $ACC3,$ACC3,$T1.2d // h2 -> h3 + + ushr $T0.2d,$ACC0,#26 + and $ACC0,$ACC0,$MASK.2d + ushr $T1.2d,$ACC3,#26 + and $ACC3,$ACC3,$MASK.2d + add $ACC1,$ACC1,$T0.2d // h0 -> h1 + add $ACC4,$ACC4,$T1.2d // h3 -> h4 + + //////////////////////////////////////////////////////////////// + // write the result, can be partially reduced + + st4 {$ACC0,$ACC1,$ACC2,$ACC3}[0],[$ctx],#16 + st1 {$ACC4}[0],[$ctx] + +.Lno_data_neon: + ldr x29,[sp],#80 + ret +.size poly1305_blocks_neon,.-poly1305_blocks_neon + +.type poly1305_emit_neon,%function +.align 5 +poly1305_emit_neon: + ldr $is_base2_26,[$ctx,#24] + cbz $is_base2_26,poly1305_emit + + ldp w10,w11,[$ctx] // load hash value base 2^26 + ldp w12,w13,[$ctx,#8] + ldr w14,[$ctx,#16] + + add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64 + lsr $h1,x12,#12 + adds $h0,$h0,x12,lsl#52 + add $h1,$h1,x13,lsl#14 + adc $h1,$h1,xzr + lsr $h2,x14,#24 + adds $h1,$h1,x14,lsl#40 + adc $h2,$h2,xzr // can be partially reduced... + + ldp $t0,$t1,[$nonce] // load nonce + + and $d0,$h2,#-4 // ... so reduce + add $d0,$d0,$h2,lsr#2 + and $h2,$h2,#3 + adds $h0,$h0,$d0 + adc $h1,$h1,xzr + + adds $d0,$h0,#5 // compare to modulus + adcs $d1,$h1,xzr + adc $d2,$h2,xzr + + tst $d2,#-4 // see if it's carried/borrowed + + csel $h0,$h0,$d0,eq + csel $h1,$h1,$d1,eq + +#ifdef __ARMEB__ + ror $t0,$t0,#32 // flip nonce words + ror $t1,$t1,#32 +#endif + adds $h0,$h0,$t0 // accumulate nonce + adc $h1,$h1,$t1 +#ifdef __ARMEB__ + rev $h0,$h0 // flip output bytes + rev $h1,$h1 +#endif + stp $h0,$h1,[$mac] // write result + + ret +.size poly1305_emit_neon,.-poly1305_emit_neon + +.align 5 +.Lzeros: +.long 0,0,0,0,0,0,0,0 +.LOPENSSL_armcap_P: +#ifdef __ILP32__ +.long OPENSSL_armcap_P-. +#else +.quad OPENSSL_armcap_P-. +#endif +.asciz "Poly1305 for ARMv8, CRYPTOGAMS by " +.align 2 +___ + +foreach (split("\n",$code)) { + s/\b(shrn\s+v[0-9]+)\.[24]d/$1.2s/ or + s/\b(fmov\s+)v([0-9]+)[^,]*,\s*x([0-9]+)/$1d$2,x$3/ or + (m/\bdup\b/ and (s/\.[24]s/.2d/g or 1)) or + (m/\b(eor|and)/ and (s/\.[248][sdh]/.16b/g or 1)) or + (m/\bum(ul|la)l\b/ and (s/\.4s/.2s/g or 1)) or + (m/\bum(ul|la)l2\b/ and (s/\.2s/.4s/g or 1)) or + (m/\bst[1-4]\s+{[^}]+}\[/ and (s/\.[24]d/.s/g or 1)); + + s/\.[124]([sd])\[/.$1\[/; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/poly1305/asm/poly1305-x86.pl b/external/boringssl/crypto/poly1305/asm/poly1305-x86.pl new file mode 100755 index 0000000000..4ad2289e6d --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-x86.pl @@ -0,0 +1,1788 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 Poly1305 hash for x86. +# +# April 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# measured with rdtsc at fixed clock frequency. +# +# IALU/gcc-3.4(*) SSE2(**) AVX2 +# Pentium 15.7/+80% - +# PIII 6.21/+90% - +# P4 19.8/+40% 3.24 +# Core 2 4.85/+90% 1.80 +# Westmere 4.58/+100% 1.43 +# Sandy Bridge 3.90/+100% 1.36 +# Haswell 3.88/+70% 1.18 0.72 +# Silvermont 11.0/+40% 4.80 +# VIA Nano 6.71/+90% 2.47 +# Sledgehammer 3.51/+180% 4.27 +# Bulldozer 4.53/+140% 1.31 +# +# (*) gcc 4.8 for some reason generated worse code; +# (**) besides SSE2 there are floating-point and AVX options; FP +# is deemed unnecessary, because pre-SSE2 processor are too +# old to care about, while it's not the fastest option on +# SSE2-capable ones; AVX is omitted, because it doesn't give +# a lot of improvement, 5-10% depending on processor; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"poly1305-x86.pl",$ARGV[$#ARGV] eq "386"); + +$sse2=$avx=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +if ($sse2) { + &static_label("const_sse2"); + &static_label("enter_blocks"); + &static_label("enter_emit"); + &external_label("OPENSSL_ia32cap_P"); + + # This may be set to 2, but valgrind can't do AVX2 on 32-bit. Without a + # way to verify test coverage, keep it disabled. + $avx = 0; +} + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^32 +# unsigned __int32 pad; # is_base2_26 in vector context +# unsigned __int32 r[4]; # key value base 2^32 + +&align(64); +&function_begin("poly1305_init"); + &mov ("edi",&wparam(0)); # context + &mov ("esi",&wparam(1)); # key + &mov ("ebp",&wparam(2)); # function table + + &xor ("eax","eax"); + &mov (&DWP(4*0,"edi"),"eax"); # zero hash value + &mov (&DWP(4*1,"edi"),"eax"); + &mov (&DWP(4*2,"edi"),"eax"); + &mov (&DWP(4*3,"edi"),"eax"); + &mov (&DWP(4*4,"edi"),"eax"); + &mov (&DWP(4*5,"edi"),"eax"); # is_base2_26 + + &cmp ("esi",0); + &je (&label("nokey")); + + if ($sse2) { + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("ebx"); + + &lea ("eax",&DWP("poly1305_blocks-".&label("pic_point"),"ebx")); + &lea ("edx",&DWP("poly1305_emit-".&label("pic_point"),"ebx")); + + &picmeup("edi","OPENSSL_ia32cap_P","ebx",&label("pic_point")); + &mov ("ecx",&DWP(0,"edi")); + &and ("ecx",1<<26|1<<24); + &cmp ("ecx",1<<26|1<<24); # SSE2 and XMM? + &jne (&label("no_sse2")); + + &lea ("eax",&DWP("_poly1305_blocks_sse2-".&label("pic_point"),"ebx")); + &lea ("edx",&DWP("_poly1305_emit_sse2-".&label("pic_point"),"ebx")); + + if ($avx>1) { + &mov ("ecx",&DWP(8,"edi")); + &test ("ecx",1<<5); # AVX2? + &jz (&label("no_sse2")); + + &lea ("eax",&DWP("_poly1305_blocks_avx2-".&label("pic_point"),"ebx")); + } + &set_label("no_sse2"); + &mov ("edi",&wparam(0)); # reload context + &mov (&DWP(0,"ebp"),"eax"); # fill function table + &mov (&DWP(4,"ebp"),"edx"); + } + + &mov ("eax",&DWP(4*0,"esi")); # load input key + &mov ("ebx",&DWP(4*1,"esi")); + &mov ("ecx",&DWP(4*2,"esi")); + &mov ("edx",&DWP(4*3,"esi")); + &and ("eax",0x0fffffff); + &and ("ebx",0x0ffffffc); + &and ("ecx",0x0ffffffc); + &and ("edx",0x0ffffffc); + &mov (&DWP(4*6,"edi"),"eax"); + &mov (&DWP(4*7,"edi"),"ebx"); + &mov (&DWP(4*8,"edi"),"ecx"); + &mov (&DWP(4*9,"edi"),"edx"); + + &mov ("eax",$sse2); +&set_label("nokey"); +&function_end("poly1305_init"); + +($h0,$h1,$h2,$h3,$h4, + $d0,$d1,$d2,$d3, + $r0,$r1,$r2,$r3, + $s1,$s2,$s3)=map(4*$_,(0..15)); + +&function_begin("poly1305_blocks"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len +&set_label("enter_blocks"); + &and ("ecx",-15); + &jz (&label("nodata")); + + &stack_push(16); + &mov ("eax",&DWP(4*6,"edi")); # r0 + &mov ("ebx",&DWP(4*7,"edi")); # r1 + &lea ("ebp",&DWP(0,"esi","ecx")); # end of input + &mov ("ecx",&DWP(4*8,"edi")); # r2 + &mov ("edx",&DWP(4*9,"edi")); # r3 + + &mov (&wparam(2),"ebp"); + &mov ("ebp","esi"); + + &mov (&DWP($r0,"esp"),"eax"); # r0 + &mov ("eax","ebx"); + &shr ("eax",2); + &mov (&DWP($r1,"esp"),"ebx"); # r1 + &add ("eax","ebx"); # s1 + &mov ("ebx","ecx"); + &shr ("ebx",2); + &mov (&DWP($r2,"esp"),"ecx"); # r2 + &add ("ebx","ecx"); # s2 + &mov ("ecx","edx"); + &shr ("ecx",2); + &mov (&DWP($r3,"esp"),"edx"); # r3 + &add ("ecx","edx"); # s3 + &mov (&DWP($s1,"esp"),"eax"); # s1 + &mov (&DWP($s2,"esp"),"ebx"); # s2 + &mov (&DWP($s3,"esp"),"ecx"); # s3 + + &mov ("eax",&DWP(4*0,"edi")); # load hash value + &mov ("ebx",&DWP(4*1,"edi")); + &mov ("ecx",&DWP(4*2,"edi")); + &mov ("esi",&DWP(4*3,"edi")); + &mov ("edi",&DWP(4*4,"edi")); + &jmp (&label("loop")); + +&set_label("loop",32); + &add ("eax",&DWP(4*0,"ebp")); # accumulate input + &adc ("ebx",&DWP(4*1,"ebp")); + &adc ("ecx",&DWP(4*2,"ebp")); + &adc ("esi",&DWP(4*3,"ebp")); + &lea ("ebp",&DWP(4*4,"ebp")); + &adc ("edi",&wparam(3)); # padbit + + &mov (&DWP($h0,"esp"),"eax"); # put aside hash[+inp] + &mov (&DWP($h3,"esp"),"esi"); + + &mul (&DWP($r0,"esp")); # h0*r0 + &mov (&DWP($h4,"esp"),"edi"); + &mov ("edi","eax"); + &mov ("eax","ebx"); # h1 + &mov ("esi","edx"); + &mul (&DWP($s3,"esp")); # h1*s3 + &add ("edi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("esi","edx"); + &mul (&DWP($s2,"esp")); # h2*s2 + &add ("edi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("esi","edx"); + &mul (&DWP($s1,"esp")); # h3*s1 + &add ("edi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("esi","edx"); + + &mul (&DWP($r1,"esp")); # h0*r1 + &mov (&DWP($d0,"esp"),"edi"); + &xor ("edi","edi"); + &add ("esi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("edi","edx"); + &mul (&DWP($r0,"esp")); # h1*r0 + &add ("esi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("edi","edx"); + &mul (&DWP($s3,"esp")); # h2*s3 + &add ("esi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("edi","edx"); + &mul (&DWP($s2,"esp")); # h3*s2 + &add ("esi","eax"); + &mov ("eax",&DWP($h4,"esp")); + &adc ("edi","edx"); + &imul ("eax",&DWP($s1,"esp")); # h4*s1 + &add ("esi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("edi",0); + + &mul (&DWP($r2,"esp")); # h0*r2 + &mov (&DWP($d1,"esp"),"esi"); + &xor ("esi","esi"); + &add ("edi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("esi","edx"); + &mul (&DWP($r1,"esp")); # h1*r1 + &add ("edi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("esi","edx"); + &mul (&DWP($r0,"esp")); # h2*r0 + &add ("edi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("esi","edx"); + &mul (&DWP($s3,"esp")); # h3*s3 + &add ("edi","eax"); + &mov ("eax",&DWP($h4,"esp")); + &adc ("esi","edx"); + &imul ("eax",&DWP($s2,"esp")); # h4*s2 + &add ("edi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("esi",0); + + &mul (&DWP($r3,"esp")); # h0*r3 + &mov (&DWP($d2,"esp"),"edi"); + &xor ("edi","edi"); + &add ("esi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("edi","edx"); + &mul (&DWP($r2,"esp")); # h1*r2 + &add ("esi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("edi","edx"); + &mul (&DWP($r1,"esp")); # h2*r1 + &add ("esi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("edi","edx"); + &mul (&DWP($r0,"esp")); # h3*r0 + &add ("esi","eax"); + &mov ("ecx",&DWP($h4,"esp")); + &adc ("edi","edx"); + + &mov ("edx","ecx"); + &imul ("ecx",&DWP($s3,"esp")); # h4*s3 + &add ("esi","ecx"); + &mov ("eax",&DWP($d0,"esp")); + &adc ("edi",0); + + &imul ("edx",&DWP($r0,"esp")); # h4*r0 + &add ("edx","edi"); + + &mov ("ebx",&DWP($d1,"esp")); + &mov ("ecx",&DWP($d2,"esp")); + + &mov ("edi","edx"); # last reduction step + &shr ("edx",2); + &and ("edi",3); + &lea ("edx",&DWP(0,"edx","edx",4)); # *5 + &add ("eax","edx"); + &adc ("ebx",0); + &adc ("ecx",0); + &adc ("esi",0); + + &cmp ("ebp",&wparam(2)); # done yet? + &jne (&label("loop")); + + &mov ("edx",&wparam(0)); # ctx + &stack_pop(16); + &mov (&DWP(4*0,"edx"),"eax"); # store hash value + &mov (&DWP(4*1,"edx"),"ebx"); + &mov (&DWP(4*2,"edx"),"ecx"); + &mov (&DWP(4*3,"edx"),"esi"); + &mov (&DWP(4*4,"edx"),"edi"); +&set_label("nodata"); +&function_end("poly1305_blocks"); + +&function_begin("poly1305_emit"); + &mov ("ebp",&wparam(0)); # context +&set_label("enter_emit"); + &mov ("edi",&wparam(1)); # output + &mov ("eax",&DWP(4*0,"ebp")); # load hash value + &mov ("ebx",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("esi",&DWP(4*4,"ebp")); + + &add ("eax",5); # compare to modulus + &adc ("ebx",0); + &adc ("ecx",0); + &adc ("edx",0); + &adc ("esi",0); + &shr ("esi",2); # did it carry/borrow? + &neg ("esi"); # do we choose hash-modulus? + + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ebx"); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); + + ¬ ("esi"); # or original hash value? + &mov ("eax",&DWP(4*0,"ebp")); + &mov ("ebx",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("ebp",&wparam(2)); + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &or ("eax",&DWP(4*0,"edi")); + &or ("ebx",&DWP(4*1,"edi")); + &or ("ecx",&DWP(4*2,"edi")); + &or ("edx",&DWP(4*3,"edi")); + + &add ("eax",&DWP(4*0,"ebp")); # accumulate key + &adc ("ebx",&DWP(4*1,"ebp")); + &adc ("ecx",&DWP(4*2,"ebp")); + &adc ("edx",&DWP(4*3,"ebp")); + + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ebx"); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); +&function_end("poly1305_emit"); + +if ($sse2) { +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^26 +# unsigned __int32 is_base2_26; +# unsigned __int32 r[4]; # key value base 2^32 +# unsigned __int32 pad[2]; +# struct { unsigned __int32 r^4, r^3, r^2, r^1; } r[9]; +# +# where r^n are base 2^26 digits of degrees of multiplier key. There are +# 5 digits, but last four are interleaved with multiples of 5, totalling +# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4. + +my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("xmm$_",(0..7)); +my $MASK=$T2; # borrow and keep in mind + +&align (32); +&function_begin_B("_poly1305_init_sse2"); + &movdqu ($D4,&QWP(4*6,"edi")); # key base 2^32 + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &mov ("ebp","esp"); + &sub ("esp",16*(9+5)); + &and ("esp",-16); + + #&pand ($D4,&QWP(96,"ebx")); # magic mask + &movq ($MASK,&QWP(64,"ebx")); + + &movdqa ($D0,$D4); + &movdqa ($D1,$D4); + &movdqa ($D2,$D4); + + &pand ($D0,$MASK); # -> base 2^26 + &psrlq ($D1,26); + &psrldq ($D2,6); + &pand ($D1,$MASK); + &movdqa ($D3,$D2); + &psrlq ($D2,4) + &psrlq ($D3,30); + &pand ($D2,$MASK); + &pand ($D3,$MASK); + &psrldq ($D4,13); + + &lea ("edx",&DWP(16*9,"esp")); # size optimization + &mov ("ecx",2); +&set_label("square"); + &movdqa (&QWP(16*0,"esp"),$D0); + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*2,"esp"),$D2); + &movdqa (&QWP(16*3,"esp"),$D3); + &movdqa (&QWP(16*4,"esp"),$D4); + + &movdqa ($T1,$D1); + &movdqa ($T0,$D2); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D1); # *5 + &paddd ($T0,$D2); # *5 + &movdqa (&QWP(16*5,"esp"),$T1); + &movdqa (&QWP(16*6,"esp"),$T0); + &movdqa ($T1,$D3); + &movdqa ($T0,$D4); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D3); # *5 + &paddd ($T0,$D4); # *5 + &movdqa (&QWP(16*7,"esp"),$T1); + &movdqa (&QWP(16*8,"esp"),$T0); + + &pshufd ($T1,$D0,0b01000100); + &movdqa ($T0,$D1); + &pshufd ($D1,$D1,0b01000100); + &pshufd ($D2,$D2,0b01000100); + &pshufd ($D3,$D3,0b01000100); + &pshufd ($D4,$D4,0b01000100); + &movdqa (&QWP(16*0,"edx"),$T1); + &movdqa (&QWP(16*1,"edx"),$D1); + &movdqa (&QWP(16*2,"edx"),$D2); + &movdqa (&QWP(16*3,"edx"),$D3); + &movdqa (&QWP(16*4,"edx"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($D4,$D0); # h4*r0 + &pmuludq ($D3,$D0); # h3*r0 + &pmuludq ($D2,$D0); # h2*r0 + &pmuludq ($D1,$D0); # h1*r0 + &pmuludq ($D0,$T1); # h0*r0 + +sub pmuladd { +my $load = shift; +my $base = shift; $base = "esp" if (!defined($base)); + + ################################################################ + # As for choice to "rotate" $T0-$T2 in order to move paddq + # past next multiplication. While it makes code harder to read + # and doesn't have significant effect on most processors, it + # makes a lot of difference on Atom, up to 30% improvement. + + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*3,$base)); # r1*h3 + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*2,$base)); # r1*h2 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*1,$base)); # r1*h1 + &paddq ($D3,$T1); + &$load ($T1,5); # s1 + &pmuludq ($T0,&QWP(16*0,$base)); # r1*h0 + &paddq ($D2,$T2); + &pmuludq ($T1,&QWP(16*4,$base)); # s1*h4 + &$load ($T2,2); # r2^n + &paddq ($D1,$T0); + + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*2,$base)); # r2*h2 + &paddq ($D0,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*1,$base)); # r2*h1 + &paddq ($D4,$T2); + &$load ($T2,6); # s2^n + &pmuludq ($T1,&QWP(16*0,$base)); # r2*h0 + &paddq ($D3,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*4,$base)); # s2*h4 + &paddq ($D2,$T1); + &pmuludq ($T0,&QWP(16*3,$base)); # s2*h3 + &$load ($T1,3); # r3^n + &paddq ($D1,$T2); + + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*1,$base)); # r3*h1 + &paddq ($D0,$T0); + &$load ($T0,7); # s3^n + &pmuludq ($T2,&QWP(16*0,$base)); # r3*h0 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*4,$base)); # s3*h4 + &paddq ($D3,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*3,$base)); # s3*h3 + &paddq ($D2,$T0); + &pmuludq ($T2,&QWP(16*2,$base)); # s3*h2 + &$load ($T0,4); # r4^n + &paddq ($D1,$T1); + + &$load ($T1,8); # s4^n + &pmuludq ($T0,&QWP(16*0,$base)); # r4*h0 + &paddq ($D0,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*4,$base)); # s4*h4 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*1,$base)); # s4*h1 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*2,$base)); # s4*h2 + &paddq ($D0,$T2); + &pmuludq ($T1,&QWP(16*3,$base)); # s4*h3 + &movdqa ($MASK,&QWP(64,"ebx")); + &paddq ($D1,$T0); + &paddq ($D2,$T1); +} + &pmuladd (sub { my ($reg,$i)=@_; + &movdqa ($reg,&QWP(16*$i,"esp")); + },"edx"); + +sub lazy_reduction { +my $extra = shift; +my $paddx = defined($extra) ? paddq : paddd; + + ################################################################ + # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + # and P. Schwabe + + &movdqa ($T0,$D3); + &pand ($D3,$MASK); + &psrlq ($T0,26); + &$extra () if (defined($extra)); + &paddq ($T0,$D4); # h3 -> h4 + &movdqa ($T1,$D0); + &pand ($D0,$MASK); + &psrlq ($T1,26); + &movdqa ($D4,$T0); + &paddq ($T1,$D1); # h0 -> h1 + &psrlq ($T0,26); + &pand ($D4,$MASK); + &movdqa ($D1,$T1); + &psrlq ($T1,26); + &paddd ($D0,$T0); # favour paddd when + # possible, because + # paddq is "broken" + # on Atom + &psllq ($T0,2); + &paddq ($T1,$D2); # h1 -> h2 + &$paddx ($T0,$D0); # h4 -> h0 + &pand ($D1,$MASK); + &movdqa ($D2,$T1); + &psrlq ($T1,26); + &pand ($D2,$MASK); + &paddd ($T1,$D3); # h2 -> h3 + &movdqa ($D0,$T0); + &psrlq ($T0,26); + &movdqa ($D3,$T1); + &psrlq ($T1,26); + &pand ($D0,$MASK); + &paddd ($D1,$T0); # h0 -> h1 + &pand ($D3,$MASK); + &paddd ($D4,$T1); # h3 -> h4 +} + &lazy_reduction (); + + &dec ("ecx"); + &jz (&label("square_break")); + + &punpcklqdq ($D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2 + &punpcklqdq ($D1,&QWP(16*1,"esp")); + &punpcklqdq ($D2,&QWP(16*2,"esp")); + &punpcklqdq ($D3,&QWP(16*3,"esp")); + &punpcklqdq ($D4,&QWP(16*4,"esp")); + &jmp (&label("square")); + +&set_label("square_break"); + &psllq ($D0,32); # -> r^3:0:r^4:0 + &psllq ($D1,32); + &psllq ($D2,32); + &psllq ($D3,32); + &psllq ($D4,32); + &por ($D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2 + &por ($D1,&QWP(16*1,"esp")); + &por ($D2,&QWP(16*2,"esp")); + &por ($D3,&QWP(16*3,"esp")); + &por ($D4,&QWP(16*4,"esp")); + + &pshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4 + &pshufd ($D1,$D1,0b10001101); + &pshufd ($D2,$D2,0b10001101); + &pshufd ($D3,$D3,0b10001101); + &pshufd ($D4,$D4,0b10001101); + + &movdqu (&QWP(16*0,"edi"),$D0); # save the table + &movdqu (&QWP(16*1,"edi"),$D1); + &movdqu (&QWP(16*2,"edi"),$D2); + &movdqu (&QWP(16*3,"edi"),$D3); + &movdqu (&QWP(16*4,"edi"),$D4); + + &movdqa ($T1,$D1); + &movdqa ($T0,$D2); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D1); # *5 + &paddd ($T0,$D2); # *5 + &movdqu (&QWP(16*5,"edi"),$T1); + &movdqu (&QWP(16*6,"edi"),$T0); + &movdqa ($T1,$D3); + &movdqa ($T0,$D4); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D3); # *5 + &paddd ($T0,$D4); # *5 + &movdqu (&QWP(16*7,"edi"),$T1); + &movdqu (&QWP(16*8,"edi"),$T0); + + &mov ("esp","ebp"); + &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization + &ret (); +&function_end_B("_poly1305_init_sse2"); + +&align (32); +&function_begin("_poly1305_blocks_sse2"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len + + &mov ("eax",&DWP(4*5,"edi")); # is_base2_26 + &and ("ecx",-16); + &jz (&label("nodata")); + &cmp ("ecx",64); + &jae (&label("enter_sse2")); + &test ("eax","eax"); # is_base2_26? + &jz (&label("enter_blocks")); + +&set_label("enter_sse2",16); + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx")); + + &test ("eax","eax"); # is_base2_26? + &jnz (&label("base2_26")); + + &call ("_poly1305_init_sse2"); + + ################################################# base 2^32 -> base 2^26 + &mov ("eax",&DWP(0,"edi")); + &mov ("ecx",&DWP(3,"edi")); + &mov ("edx",&DWP(6,"edi")); + &mov ("esi",&DWP(9,"edi")); + &mov ("ebp",&DWP(13,"edi")); + &mov (&DWP(4*5,"edi"),1); # is_base2_26 + + &shr ("ecx",2); + &and ("eax",0x3ffffff); + &shr ("edx",4); + &and ("ecx",0x3ffffff); + &shr ("esi",6); + &and ("edx",0x3ffffff); + + &movd ($D0,"eax"); + &movd ($D1,"ecx"); + &movd ($D2,"edx"); + &movd ($D3,"esi"); + &movd ($D4,"ebp"); + + &mov ("esi",&wparam(1)); # [reload] inp + &mov ("ecx",&wparam(2)); # [reload] len + &jmp (&label("base2_32")); + +&set_label("base2_26",16); + &movd ($D0,&DWP(4*0,"edi")); # load hash value + &movd ($D1,&DWP(4*1,"edi")); + &movd ($D2,&DWP(4*2,"edi")); + &movd ($D3,&DWP(4*3,"edi")); + &movd ($D4,&DWP(4*4,"edi")); + &movdqa ($MASK,&QWP(64,"ebx")); + +&set_label("base2_32"); + &mov ("eax",&wparam(3)); # padbit + &mov ("ebp","esp"); + + &sub ("esp",16*(5+5+5+9+9)); + &and ("esp",-16); + + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &shl ("eax",24); # padbit + + &test ("ecx",31); + &jz (&label("even")); + + ################################################################ + # process single block, with SSE2, because it's still faster + # even though half of result is discarded + + &movdqu ($T1,&QWP(0,"esi")); # input + &lea ("esi",&DWP(16,"esi")); + + &movdqa ($T0,$T1); # -> base 2^26 ... + &pand ($T1,$MASK); + &paddd ($D0,$T1); # ... and accumuate + + &movdqa ($T1,$T0); + &psrlq ($T0,26); + &psrldq ($T1,6); + &pand ($T0,$MASK); + &paddd ($D1,$T0); + + &movdqa ($T0,$T1); + &psrlq ($T1,4); + &pand ($T1,$MASK); + &paddd ($D2,$T1); + + &movdqa ($T1,$T0); + &psrlq ($T0,30); + &pand ($T0,$MASK); + &psrldq ($T1,7); + &paddd ($D3,$T0); + + &movd ($T0,"eax"); # padbit + &paddd ($D4,$T1); + &movd ($T1,&DWP(16*0+12,"edi")); # r0 + &paddd ($D4,$T0); + + &movdqa (&QWP(16*0,"esp"),$D0); + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*2,"esp"),$D2); + &movdqa (&QWP(16*3,"esp"),$D3); + &movdqa (&QWP(16*4,"esp"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($D0,$T1); # h4*r0 + &pmuludq ($D1,$T1); # h3*r0 + &pmuludq ($D2,$T1); # h2*r0 + &movd ($T0,&DWP(16*1+12,"edi")); # r1 + &pmuludq ($D3,$T1); # h1*r0 + &pmuludq ($D4,$T1); # h0*r0 + + &pmuladd (sub { my ($reg,$i)=@_; + &movd ($reg,&DWP(16*$i+12,"edi")); + }); + + &lazy_reduction (); + + &sub ("ecx",16); + &jz (&label("done")); + +&set_label("even"); + &lea ("edx",&DWP(16*(5+5+5+9),"esp"));# size optimization + &lea ("eax",&DWP(-16*2,"esi")); + &sub ("ecx",64); + + ################################################################ + # expand and copy pre-calculated table to stack + + &movdqu ($T0,&QWP(16*0,"edi")); # r^1:r^2:r^3:r^4 + &pshufd ($T1,$T0,0b01000100); # duplicate r^3:r^4 + &cmovb ("esi","eax"); + &pshufd ($T0,$T0,0b11101110); # duplicate r^1:r^2 + &movdqa (&QWP(16*0,"edx"),$T1); + &lea ("eax",&DWP(16*10,"esp")); + &movdqu ($T1,&QWP(16*1,"edi")); + &movdqa (&QWP(16*(0-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*1,"edx"),$T0); + &movdqu ($T0,&QWP(16*2,"edi")); + &movdqa (&QWP(16*(1-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*2,"edx"),$T1); + &movdqu ($T1,&QWP(16*3,"edi")); + &movdqa (&QWP(16*(2-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*3,"edx"),$T0); + &movdqu ($T0,&QWP(16*4,"edi")); + &movdqa (&QWP(16*(3-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*4,"edx"),$T1); + &movdqu ($T1,&QWP(16*5,"edi")); + &movdqa (&QWP(16*(4-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*5,"edx"),$T0); + &movdqu ($T0,&QWP(16*6,"edi")); + &movdqa (&QWP(16*(5-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*6,"edx"),$T1); + &movdqu ($T1,&QWP(16*7,"edi")); + &movdqa (&QWP(16*(6-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*7,"edx"),$T0); + &movdqu ($T0,&QWP(16*8,"edi")); + &movdqa (&QWP(16*(7-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*8,"edx"),$T1); + &movdqa (&QWP(16*(8-9),"edx"),$T0); + +sub load_input { +my ($inpbase,$offbase)=@_; + + &movdqu ($T0,&QWP($inpbase+0,"esi")); # load input + &movdqu ($T1,&QWP($inpbase+16,"esi")); + &lea ("esi",&DWP(16*2,"esi")); + + &movdqa (&QWP($offbase+16*2,"esp"),$D2); + &movdqa (&QWP($offbase+16*3,"esp"),$D3); + &movdqa (&QWP($offbase+16*4,"esp"),$D4); + + &movdqa ($D2,$T0); # splat input + &movdqa ($D3,$T1); + &psrldq ($D2,6); + &psrldq ($D3,6); + &movdqa ($D4,$T0); + &punpcklqdq ($D2,$D3); # 2:3 + &punpckhqdq ($D4,$T1); # 4 + &punpcklqdq ($T0,$T1); # 0:1 + + &movdqa ($D3,$D2); + &psrlq ($D2,4); + &psrlq ($D3,30); + &movdqa ($T1,$T0); + &psrlq ($D4,40); # 4 + &psrlq ($T1,26); + &pand ($T0,$MASK); # 0 + &pand ($T1,$MASK); # 1 + &pand ($D2,$MASK); # 2 + &pand ($D3,$MASK); # 3 + &por ($D4,&QWP(0,"ebx")); # padbit, yes, always + + &movdqa (&QWP($offbase+16*0,"esp"),$D0) if ($offbase); + &movdqa (&QWP($offbase+16*1,"esp"),$D1) if ($offbase); +} + &load_input (16*2,16*5); + + &jbe (&label("skip_loop")); + &jmp (&label("loop")); + +&set_label("loop",32); + ################################################################ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + # \___________________/ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + # \___________________/ \____________________/ + ################################################################ + + &movdqa ($T2,&QWP(16*(0-9),"edx")); # r0^2 + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 = h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1 + # d3 = h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4 + # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + # d1 = h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2 + # d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + &movdqa ($D1,$T0); + &pmuludq ($T0,$T2); # h0*r0 + &movdqa ($D0,$T1); + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &pmuludq ($D3,$T2); # h3*r0 + &pmuludq ($D4,$T2); # h4*r0 + +sub pmuladd_alt { +my $addr = shift; + + &pmuludq ($D0,&$addr(8)); # h1*s4 + &movdqa ($T2,$D1); + &pmuludq ($D1,&$addr(1)); # h0*r1 + &paddq ($D0,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(2)); # h0*r2 + &paddq ($D1,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(3)); # h0*r3 + &paddq ($D2,$T2); + &movdqa ($T2,&QWP(16*1,"eax")); # pull h1 + &pmuludq ($T1,&$addr(4)); # h0*r4 + &paddq ($D3,$T0); + + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(1)); # h1*r1 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(2)); # h1*r2 + &paddq ($D2,$T2); + &movdqa ($T2,&QWP(16*2,"eax")); # pull h2 + &pmuludq ($T1,&$addr(3)); # h1*r3 + &paddq ($D3,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(7)); # h2*s3 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(8)); # h2*s4 + &paddq ($D0,$T2); + + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(1)); # h2*r1 + &paddq ($D1,$T0); + &movdqa ($T0,&QWP(16*3,"eax")); # pull h3 + &pmuludq ($T2,&$addr(2)); # h2*r2 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(6)); # h3*s2 + &paddq ($D4,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(7)); # h3*s3 + &paddq ($D0,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(8)); # h3*s4 + &paddq ($D1,$T1); + + &movdqa ($T1,&QWP(16*4,"eax")); # pull h4 + &pmuludq ($T0,&$addr(1)); # h3*r1 + &paddq ($D2,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(8)); # h4*s4 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(5)); # h4*s1 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(6)); # h4*s2 + &paddq ($D0,$T2); + &movdqa ($MASK,&QWP(64,"ebx")); + &pmuludq ($T1,&$addr(7)); # h4*s3 + &paddq ($D1,$T0); + &paddq ($D2,$T1); +} + &pmuladd_alt (sub { my $i=shift; &QWP(16*($i-9),"edx"); }); + + &load_input (-16*2,0); + &lea ("eax",&DWP(-16*2,"esi")); + &sub ("ecx",64); + + &paddd ($T0,&QWP(16*(5+0),"esp")); # add hash value + &paddd ($T1,&QWP(16*(5+1),"esp")); + &paddd ($D2,&QWP(16*(5+2),"esp")); + &paddd ($D3,&QWP(16*(5+3),"esp")); + &paddd ($D4,&QWP(16*(5+4),"esp")); + + &cmovb ("esi","eax"); + &lea ("eax",&DWP(16*10,"esp")); + + &movdqa ($T2,&QWP(16*0,"edx")); # r0^4 + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 += h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1 + # d3 += h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4 + # d2 += h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + # d1 += h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2 + # d0 += h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + &movdqa ($D1,$T0); + &pmuludq ($T0,$T2); # h0*r0 + &paddq ($T0,$D0); + &movdqa ($D0,$T1); + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &pmuludq ($D3,$T2); # h3*r0 + &pmuludq ($D4,$T2); # h4*r0 + + &paddq ($T1,&QWP(16*1,"esp")); + &paddq ($D2,&QWP(16*2,"esp")); + &paddq ($D3,&QWP(16*3,"esp")); + &paddq ($D4,&QWP(16*4,"esp")); + + &pmuladd_alt (sub { my $i=shift; &QWP(16*$i,"edx"); }); + + &lazy_reduction (); + + &load_input (16*2,16*5); + + &ja (&label("loop")); + +&set_label("skip_loop"); + ################################################################ + # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + &pshufd ($T2,&QWP(16*(0-9),"edx"),0x10);# r0^n + &add ("ecx",32); + &jnz (&label("long_tail")); + + &paddd ($T0,$D0); # add hash value + &paddd ($T1,$D1); + &paddd ($D2,&QWP(16*7,"esp")); + &paddd ($D3,&QWP(16*8,"esp")); + &paddd ($D4,&QWP(16*9,"esp")); + +&set_label("long_tail"); + + &movdqa (&QWP(16*0,"eax"),$T0); + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($T0,$T2); # h0*r0 + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &movdqa ($D0,$T0); + &pshufd ($T0,&QWP(16*(1-9),"edx"),0x10);# r1^n + &pmuludq ($D3,$T2); # h3*r0 + &movdqa ($D1,$T1); + &pmuludq ($D4,$T2); # h4*r0 + + &pmuladd (sub { my ($reg,$i)=@_; + &pshufd ($reg,&QWP(16*($i-9),"edx"),0x10); + },"eax"); + + &jz (&label("short_tail")); + + &load_input (-16*2,0); + + &pshufd ($T2,&QWP(16*0,"edx"),0x10); # r0^n + &paddd ($T0,&QWP(16*5,"esp")); # add hash value + &paddd ($T1,&QWP(16*6,"esp")); + &paddd ($D2,&QWP(16*7,"esp")); + &paddd ($D3,&QWP(16*8,"esp")); + &paddd ($D4,&QWP(16*9,"esp")); + + ################################################################ + # multiply inp[0:1] by r^4:r^3 and accumulate + + &movdqa (&QWP(16*0,"esp"),$T0); + &pmuludq ($T0,$T2); # h0*r0 + &movdqa (&QWP(16*1,"esp"),$T1); + &pmuludq ($T1,$T2); # h1*r0 + &paddq ($D0,$T0); + &movdqa ($T0,$D2); + &pmuludq ($D2,$T2); # h2*r0 + &paddq ($D1,$T1); + &movdqa ($T1,$D3); + &pmuludq ($D3,$T2); # h3*r0 + &paddq ($D2,&QWP(16*2,"esp")); + &movdqa (&QWP(16*2,"esp"),$T0); + &pshufd ($T0,&QWP(16*1,"edx"),0x10); # r1^n + &paddq ($D3,&QWP(16*3,"esp")); + &movdqa (&QWP(16*3,"esp"),$T1); + &movdqa ($T1,$D4); + &pmuludq ($D4,$T2); # h4*r0 + &paddq ($D4,&QWP(16*4,"esp")); + &movdqa (&QWP(16*4,"esp"),$T1); + + &pmuladd (sub { my ($reg,$i)=@_; + &pshufd ($reg,&QWP(16*$i,"edx"),0x10); + }); + +&set_label("short_tail"); + + ################################################################ + # horizontal addition + + &pshufd ($T1,$D4,0b01001110); + &pshufd ($T0,$D3,0b01001110); + &paddq ($D4,$T1); + &paddq ($D3,$T0); + &pshufd ($T1,$D0,0b01001110); + &pshufd ($T0,$D1,0b01001110); + &paddq ($D0,$T1); + &paddq ($D1,$T0); + &pshufd ($T1,$D2,0b01001110); + #&paddq ($D2,$T1); + + &lazy_reduction (sub { &paddq ($D2,$T1) }); + +&set_label("done"); + &movd (&DWP(-16*3+4*0,"edi"),$D0); # store hash value + &movd (&DWP(-16*3+4*1,"edi"),$D1); + &movd (&DWP(-16*3+4*2,"edi"),$D2); + &movd (&DWP(-16*3+4*3,"edi"),$D3); + &movd (&DWP(-16*3+4*4,"edi"),$D4); + &mov ("esp","ebp"); +&set_label("nodata"); +&function_end("_poly1305_blocks_sse2"); + +&align (32); +&function_begin("_poly1305_emit_sse2"); + &mov ("ebp",&wparam(0)); # context + + &cmp (&DWP(4*5,"ebp"),0); # is_base2_26? + &je (&label("enter_emit")); + + &mov ("eax",&DWP(4*0,"ebp")); # load hash value + &mov ("edi",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("esi",&DWP(4*4,"ebp")); + + &mov ("ebx","edi"); # base 2^26 -> base 2^32 + &shl ("edi",26); + &shr ("ebx",6); + &add ("eax","edi"); + &mov ("edi","ecx"); + &adc ("ebx",0); + + &shl ("edi",20); + &shr ("ecx",12); + &add ("ebx","edi"); + &mov ("edi","edx"); + &adc ("ecx",0); + + &shl ("edi",14); + &shr ("edx",18); + &add ("ecx","edi"); + &mov ("edi","esi"); + &adc ("edx",0); + + &shl ("edi",8); + &shr ("esi",24); + &add ("edx","edi"); + &adc ("esi",0); # can be partially reduced + + &mov ("edi","esi"); # final reduction + &and ("esi",3); + &shr ("edi",2); + &lea ("ebp",&DWP(0,"edi","edi",4)); # *5 + &mov ("edi",&wparam(1)); # output + add ("eax","ebp"); + &mov ("ebp",&wparam(2)); # key + adc ("ebx",0); + adc ("ecx",0); + adc ("edx",0); + + &movd ($D0,"eax"); # offload original hash value + &add ("eax",5); # compare to modulus + &movd ($D1,"ebx"); + &adc ("ebx",0); + &movd ($D2,"ecx"); + &adc ("ecx",0); + &movd ($D3,"edx"); + &adc ("edx",0); + &adc ("esi",0); + &shr ("esi",2); # did it carry/borrow? + + &neg ("esi"); # do we choose (hash-modulus) ... + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &mov (&DWP(4*0,"edi"),"eax"); + &movd ("eax",$D0); + &mov (&DWP(4*1,"edi"),"ebx"); + &movd ("ebx",$D1); + &mov (&DWP(4*2,"edi"),"ecx"); + &movd ("ecx",$D2); + &mov (&DWP(4*3,"edi"),"edx"); + &movd ("edx",$D3); + + ¬ ("esi"); # ... or original hash value? + &and ("eax","esi"); + &and ("ebx","esi"); + &or ("eax",&DWP(4*0,"edi")); + &and ("ecx","esi"); + &or ("ebx",&DWP(4*1,"edi")); + &and ("edx","esi"); + &or ("ecx",&DWP(4*2,"edi")); + &or ("edx",&DWP(4*3,"edi")); + + &add ("eax",&DWP(4*0,"ebp")); # accumulate key + &adc ("ebx",&DWP(4*1,"ebp")); + &mov (&DWP(4*0,"edi"),"eax"); + &adc ("ecx",&DWP(4*2,"ebp")); + &mov (&DWP(4*1,"edi"),"ebx"); + &adc ("edx",&DWP(4*3,"ebp")); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); +&function_end("_poly1305_emit_sse2"); + +if ($avx>1) { +######################################################################## +# Note that poly1305_init_avx2 operates on %xmm, I could have used +# poly1305_init_sse2... + +&align (32); +&function_begin_B("_poly1305_init_avx2"); + &vmovdqu ($D4,&QWP(4*6,"edi")); # key base 2^32 + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &mov ("ebp","esp"); + &sub ("esp",16*(9+5)); + &and ("esp",-16); + + #&vpand ($D4,$D4,&QWP(96,"ebx")); # magic mask + &vmovdqa ($MASK,&QWP(64,"ebx")); + + &vpand ($D0,$D4,$MASK); # -> base 2^26 + &vpsrlq ($D1,$D4,26); + &vpsrldq ($D3,$D4,6); + &vpand ($D1,$D1,$MASK); + &vpsrlq ($D2,$D3,4) + &vpsrlq ($D3,$D3,30); + &vpand ($D2,$D2,$MASK); + &vpand ($D3,$D3,$MASK); + &vpsrldq ($D4,$D4,13); + + &lea ("edx",&DWP(16*9,"esp")); # size optimization + &mov ("ecx",2); +&set_label("square"); + &vmovdqa (&QWP(16*0,"esp"),$D0); + &vmovdqa (&QWP(16*1,"esp"),$D1); + &vmovdqa (&QWP(16*2,"esp"),$D2); + &vmovdqa (&QWP(16*3,"esp"),$D3); + &vmovdqa (&QWP(16*4,"esp"),$D4); + + &vpslld ($T1,$D1,2); + &vpslld ($T0,$D2,2); + &vpaddd ($T1,$T1,$D1); # *5 + &vpaddd ($T0,$T0,$D2); # *5 + &vmovdqa (&QWP(16*5,"esp"),$T1); + &vmovdqa (&QWP(16*6,"esp"),$T0); + &vpslld ($T1,$D3,2); + &vpslld ($T0,$D4,2); + &vpaddd ($T1,$T1,$D3); # *5 + &vpaddd ($T0,$T0,$D4); # *5 + &vmovdqa (&QWP(16*7,"esp"),$T1); + &vmovdqa (&QWP(16*8,"esp"),$T0); + + &vpshufd ($T0,$D0,0b01000100); + &vmovdqa ($T1,$D1); + &vpshufd ($D1,$D1,0b01000100); + &vpshufd ($D2,$D2,0b01000100); + &vpshufd ($D3,$D3,0b01000100); + &vpshufd ($D4,$D4,0b01000100); + &vmovdqa (&QWP(16*0,"edx"),$T0); + &vmovdqa (&QWP(16*1,"edx"),$D1); + &vmovdqa (&QWP(16*2,"edx"),$D2); + &vmovdqa (&QWP(16*3,"edx"),$D3); + &vmovdqa (&QWP(16*4,"edx"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &vpmuludq ($D4,$D4,$D0); # h4*r0 + &vpmuludq ($D3,$D3,$D0); # h3*r0 + &vpmuludq ($D2,$D2,$D0); # h2*r0 + &vpmuludq ($D1,$D1,$D0); # h1*r0 + &vpmuludq ($D0,$T0,$D0); # h0*r0 + + &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # r1*h3 + &vpaddq ($D4,$D4,$T0); + &vpmuludq ($T2,$T1,&QWP(16*2,"edx")); # r1*h2 + &vpaddq ($D3,$D3,$T2); + &vpmuludq ($T0,$T1,&QWP(16*1,"edx")); # r1*h1 + &vpaddq ($D2,$D2,$T0); + &vmovdqa ($T2,&QWP(16*5,"esp")); # s1 + &vpmuludq ($T1,$T1,&QWP(16*0,"edx")); # r1*h0 + &vpaddq ($D1,$D1,$T1); + &vmovdqa ($T0,&QWP(16*2,"esp")); # r2 + &vpmuludq ($T2,$T2,&QWP(16*4,"edx")); # s1*h4 + &vpaddq ($D0,$D0,$T2); + + &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # r2*h2 + &vpaddq ($D4,$D4,$T1); + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r2*h1 + &vpaddq ($D3,$D3,$T2); + &vmovdqa ($T1,&QWP(16*6,"esp")); # s2 + &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r2*h0 + &vpaddq ($D2,$D2,$T0); + &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s2*h4 + &vpaddq ($D1,$D1,$T2); + &vmovdqa ($T0,&QWP(16*3,"esp")); # r3 + &vpmuludq ($T1,$T1,&QWP(16*3,"edx")); # s2*h3 + &vpaddq ($D0,$D0,$T1); + + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r3*h1 + &vpaddq ($D4,$D4,$T2); + &vmovdqa ($T1,&QWP(16*7,"esp")); # s3 + &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r3*h0 + &vpaddq ($D3,$D3,$T0); + &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s3*h4 + &vpaddq ($D2,$D2,$T2); + &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # s3*h3 + &vpaddq ($D1,$D1,$T0); + &vmovdqa ($T2,&QWP(16*4,"esp")); # r4 + &vpmuludq ($T1,$T1,&QWP(16*2,"edx")); # s3*h2 + &vpaddq ($D0,$D0,$T1); + + &vmovdqa ($T0,&QWP(16*8,"esp")); # s4 + &vpmuludq ($T2,$T2,&QWP(16*0,"edx")); # r4*h0 + &vpaddq ($D4,$D4,$T2); + &vpmuludq ($T1,$T0,&QWP(16*4,"edx")); # s4*h4 + &vpaddq ($D3,$D3,$T1); + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # s4*h1 + &vpaddq ($D0,$D0,$T2); + &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # s4*h2 + &vpaddq ($D1,$D1,$T1); + &vmovdqa ($MASK,&QWP(64,"ebx")); + &vpmuludq ($T0,$T0,&QWP(16*3,"edx")); # s4*h3 + &vpaddq ($D2,$D2,$T0); + + ################################################################ + # lazy reduction + &vpsrlq ($T0,$D3,26); + &vpand ($D3,$D3,$MASK); + &vpsrlq ($T1,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpaddq ($D4,$D4,$T0); # h3 -> h4 + &vpaddq ($D1,$D1,$T1); # h0 -> h1 + &vpsrlq ($T0,$D4,26); + &vpand ($D4,$D4,$MASK); + &vpsrlq ($T1,$D1,26); + &vpand ($D1,$D1,$MASK); + &vpaddq ($D2,$D2,$T1); # h1 -> h2 + &vpaddd ($D0,$D0,$T0); + &vpsllq ($T0,$T0,2); + &vpsrlq ($T1,$D2,26); + &vpand ($D2,$D2,$MASK); + &vpaddd ($D0,$D0,$T0); # h4 -> h0 + &vpaddd ($D3,$D3,$T1); # h2 -> h3 + &vpsrlq ($T1,$D3,26); + &vpsrlq ($T0,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpand ($D3,$D3,$MASK); + &vpaddd ($D1,$D1,$T0); # h0 -> h1 + &vpaddd ($D4,$D4,$T1); # h3 -> h4 + + &dec ("ecx"); + &jz (&label("square_break")); + + &vpunpcklqdq ($D0,$D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2 + &vpunpcklqdq ($D1,$D1,&QWP(16*1,"esp")); + &vpunpcklqdq ($D2,$D2,&QWP(16*2,"esp")); + &vpunpcklqdq ($D3,$D3,&QWP(16*3,"esp")); + &vpunpcklqdq ($D4,$D4,&QWP(16*4,"esp")); + &jmp (&label("square")); + +&set_label("square_break"); + &vpsllq ($D0,$D0,32); # -> r^3:0:r^4:0 + &vpsllq ($D1,$D1,32); + &vpsllq ($D2,$D2,32); + &vpsllq ($D3,$D3,32); + &vpsllq ($D4,$D4,32); + &vpor ($D0,$D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2 + &vpor ($D1,$D1,&QWP(16*1,"esp")); + &vpor ($D2,$D2,&QWP(16*2,"esp")); + &vpor ($D3,$D3,&QWP(16*3,"esp")); + &vpor ($D4,$D4,&QWP(16*4,"esp")); + + &vpshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4 + &vpshufd ($D1,$D1,0b10001101); + &vpshufd ($D2,$D2,0b10001101); + &vpshufd ($D3,$D3,0b10001101); + &vpshufd ($D4,$D4,0b10001101); + + &vmovdqu (&QWP(16*0,"edi"),$D0); # save the table + &vmovdqu (&QWP(16*1,"edi"),$D1); + &vmovdqu (&QWP(16*2,"edi"),$D2); + &vmovdqu (&QWP(16*3,"edi"),$D3); + &vmovdqu (&QWP(16*4,"edi"),$D4); + + &vpslld ($T1,$D1,2); + &vpslld ($T0,$D2,2); + &vpaddd ($T1,$T1,$D1); # *5 + &vpaddd ($T0,$T0,$D2); # *5 + &vmovdqu (&QWP(16*5,"edi"),$T1); + &vmovdqu (&QWP(16*6,"edi"),$T0); + &vpslld ($T1,$D3,2); + &vpslld ($T0,$D4,2); + &vpaddd ($T1,$T1,$D3); # *5 + &vpaddd ($T0,$T0,$D4); # *5 + &vmovdqu (&QWP(16*7,"edi"),$T1); + &vmovdqu (&QWP(16*8,"edi"),$T0); + + &mov ("esp","ebp"); + &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization + &ret (); +&function_end_B("_poly1305_init_avx2"); + +######################################################################## +# now it's time to switch to %ymm + +my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("ymm$_",(0..7)); +my $MASK=$T2; + +sub X { my $reg=shift; $reg=~s/^ymm/xmm/; $reg; } + +&align (32); +&function_begin("_poly1305_blocks_avx2"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len + + &mov ("eax",&DWP(4*5,"edi")); # is_base2_26 + &and ("ecx",-16); + &jz (&label("nodata")); + &cmp ("ecx",64); + &jae (&label("enter_avx2")); + &test ("eax","eax"); # is_base2_26? + &jz (&label("enter_blocks")); + +&set_label("enter_avx2"); + &vzeroupper (); + + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx")); + + &test ("eax","eax"); # is_base2_26? + &jnz (&label("base2_26")); + + &call ("_poly1305_init_avx2"); + + ################################################# base 2^32 -> base 2^26 + &mov ("eax",&DWP(0,"edi")); + &mov ("ecx",&DWP(3,"edi")); + &mov ("edx",&DWP(6,"edi")); + &mov ("esi",&DWP(9,"edi")); + &mov ("ebp",&DWP(13,"edi")); + + &shr ("ecx",2); + &and ("eax",0x3ffffff); + &shr ("edx",4); + &and ("ecx",0x3ffffff); + &shr ("esi",6); + &and ("edx",0x3ffffff); + + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ecx"); + &mov (&DWP(4*2,"edi"),"edx"); + &mov (&DWP(4*3,"edi"),"esi"); + &mov (&DWP(4*4,"edi"),"ebp"); + &mov (&DWP(4*5,"edi"),1); # is_base2_26 + + &mov ("esi",&wparam(1)); # [reload] inp + &mov ("ecx",&wparam(2)); # [reload] len + +&set_label("base2_26"); + &mov ("eax",&wparam(3)); # padbit + &mov ("ebp","esp"); + + &sub ("esp",32*(5+9)); + &and ("esp",-512); # ensure that frame + # doesn't cross page + # boundary, which is + # essential for + # misaligned 32-byte + # loads + + ################################################################ + # expand and copy pre-calculated table to stack + + &vmovdqu (&X($D0),&QWP(16*(3+0),"edi")); + &lea ("edx",&DWP(32*5+128,"esp")); # +128 size optimization + &vmovdqu (&X($D1),&QWP(16*(3+1),"edi")); + &vmovdqu (&X($D2),&QWP(16*(3+2),"edi")); + &vmovdqu (&X($D3),&QWP(16*(3+3),"edi")); + &vmovdqu (&X($D4),&QWP(16*(3+4),"edi")); + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &vpermq ($D0,$D0,0b01000000); # 00001234 -> 12343434 + &vpermq ($D1,$D1,0b01000000); + &vpermq ($D2,$D2,0b01000000); + &vpermq ($D3,$D3,0b01000000); + &vpermq ($D4,$D4,0b01000000); + &vpshufd ($D0,$D0,0b11001000); # 12343434 -> 14243444 + &vpshufd ($D1,$D1,0b11001000); + &vpshufd ($D2,$D2,0b11001000); + &vpshufd ($D3,$D3,0b11001000); + &vpshufd ($D4,$D4,0b11001000); + &vmovdqa (&QWP(32*0-128,"edx"),$D0); + &vmovdqu (&X($D0),&QWP(16*5,"edi")); + &vmovdqa (&QWP(32*1-128,"edx"),$D1); + &vmovdqu (&X($D1),&QWP(16*6,"edi")); + &vmovdqa (&QWP(32*2-128,"edx"),$D2); + &vmovdqu (&X($D2),&QWP(16*7,"edi")); + &vmovdqa (&QWP(32*3-128,"edx"),$D3); + &vmovdqu (&X($D3),&QWP(16*8,"edi")); + &vmovdqa (&QWP(32*4-128,"edx"),$D4); + &vpermq ($D0,$D0,0b01000000); + &vpermq ($D1,$D1,0b01000000); + &vpermq ($D2,$D2,0b01000000); + &vpermq ($D3,$D3,0b01000000); + &vpshufd ($D0,$D0,0b11001000); + &vpshufd ($D1,$D1,0b11001000); + &vpshufd ($D2,$D2,0b11001000); + &vpshufd ($D3,$D3,0b11001000); + &vmovdqa (&QWP(32*5-128,"edx"),$D0); + &vmovd (&X($D0),&DWP(-16*3+4*0,"edi"));# load hash value + &vmovdqa (&QWP(32*6-128,"edx"),$D1); + &vmovd (&X($D1),&DWP(-16*3+4*1,"edi")); + &vmovdqa (&QWP(32*7-128,"edx"),$D2); + &vmovd (&X($D2),&DWP(-16*3+4*2,"edi")); + &vmovdqa (&QWP(32*8-128,"edx"),$D3); + &vmovd (&X($D3),&DWP(-16*3+4*3,"edi")); + &vmovd (&X($D4),&DWP(-16*3+4*4,"edi")); + &vmovdqa ($MASK,&QWP(64,"ebx")); + &neg ("eax"); # padbit + + &test ("ecx",63); + &jz (&label("even")); + + &mov ("edx","ecx"); + &and ("ecx",-64); + &and ("edx",63); + + &vmovdqu (&X($T0),&QWP(16*0,"esi")); + &cmp ("edx",32); + &jb (&label("one")); + + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &je (&label("two")); + + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &lea ("esi",&DWP(16*3,"esi")); + &lea ("ebx",&DWP(8,"ebx")); # three padbits + &lea ("edx",&DWP(32*5+128+8,"esp")); # --:r^1:r^2:r^3 (*) + &jmp (&label("tail")); + +&set_label("two"); + &lea ("esi",&DWP(16*2,"esi")); + &lea ("ebx",&DWP(16,"ebx")); # two padbits + &lea ("edx",&DWP(32*5+128+16,"esp"));# --:--:r^1:r^2 (*) + &jmp (&label("tail")); + +&set_label("one"); + &lea ("esi",&DWP(16*1,"esi")); + &vpxor ($T1,$T1,$T1); + &lea ("ebx",&DWP(32,"ebx","eax",8)); # one or no padbits + &lea ("edx",&DWP(32*5+128+24,"esp"));# --:--:--:r^1 (*) + &jmp (&label("tail")); + +# (*) spots marked with '--' are data from next table entry, but they +# are multiplied by 0 and therefore rendered insignificant + +&set_label("even",32); + &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1); + &lea ("esi",&DWP(16*4,"esi")); + &sub ("ecx",64); + &jz (&label("tail")); + +&set_label("loop"); + ################################################################ + # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4 + # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3 + # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2 + # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1 + # \________/ \_______/ + ################################################################ + +sub vsplat_input { + &vmovdqa (&QWP(32*2,"esp"),$D2); + &vpsrldq ($D2,$T0,6); # splat input + &vmovdqa (&QWP(32*0,"esp"),$D0); + &vpsrldq ($D0,$T1,6); + &vmovdqa (&QWP(32*1,"esp"),$D1); + &vpunpckhqdq ($D1,$T0,$T1); # 4 + &vpunpcklqdq ($T0,$T0,$T1); # 0:1 + &vpunpcklqdq ($D2,$D2,$D0); # 2:3 + + &vpsrlq ($D0,$D2,30); + &vpsrlq ($D2,$D2,4); + &vpsrlq ($T1,$T0,26); + &vpsrlq ($D1,$D1,40); # 4 + &vpand ($D2,$D2,$MASK); # 2 + &vpand ($T0,$T0,$MASK); # 0 + &vpand ($T1,$T1,$MASK); # 1 + &vpand ($D0,$D0,$MASK); # 3 (*) + &vpor ($D1,$D1,&QWP(0,"ebx")); # padbit, yes, always + + # (*) note that output is counterintuitive, inp[3:4] is + # returned in $D1-2, while $D3-4 are preserved; +} + &vsplat_input (); + +sub vpmuladd { +my $addr = shift; + + &vpaddq ($D2,$D2,&QWP(32*2,"esp")); # add hash value + &vpaddq ($T0,$T0,&QWP(32*0,"esp")); + &vpaddq ($T1,$T1,&QWP(32*1,"esp")); + &vpaddq ($D0,$D0,$D3); + &vpaddq ($D1,$D1,$D4); + + ################################################################ + # d3 = h2*r1 + h0*r3 + h1*r2 + h3*r0 + h4*5*r4 + # d4 = h2*r2 + h0*r4 + h1*r3 + h3*r1 + h4*r0 + # d0 = h2*5*r3 + h0*r0 + h1*5*r4 + h3*5*r2 + h4*5*r1 + # d1 = h2*5*r4 + h0*r1 + h1*r0 + h3*5*r3 + h4*5*r2 + # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + + &vpmuludq ($D3,$D2,&$addr(1)); # d3 = h2*r1 + &vmovdqa (QWP(32*1,"esp"),$T1); + &vpmuludq ($D4,$D2,&$addr(2)); # d4 = h2*r2 + &vmovdqa (QWP(32*3,"esp"),$D0); + &vpmuludq ($D0,$D2,&$addr(7)); # d0 = h2*s3 + &vmovdqa (QWP(32*4,"esp"),$D1); + &vpmuludq ($D1,$D2,&$addr(8)); # d1 = h2*s4 + &vpmuludq ($D2,$D2,&$addr(0)); # d2 = h2*r0 + + &vpmuludq ($T2,$T0,&$addr(3)); # h0*r3 + &vpaddq ($D3,$D3,$T2); # d3 += h0*r3 + &vpmuludq ($T1,$T0,&$addr(4)); # h0*r4 + &vpaddq ($D4,$D4,$T1); # d4 + h0*r4 + &vpmuludq ($T2,$T0,&$addr(0)); # h0*r0 + &vpaddq ($D0,$D0,$T2); # d0 + h0*r0 + &vmovdqa ($T2,&QWP(32*1,"esp")); # h1 + &vpmuludq ($T1,$T0,&$addr(1)); # h0*r1 + &vpaddq ($D1,$D1,$T1); # d1 += h0*r1 + &vpmuludq ($T0,$T0,&$addr(2)); # h0*r2 + &vpaddq ($D2,$D2,$T0); # d2 += h0*r2 + + &vpmuludq ($T1,$T2,&$addr(2)); # h1*r2 + &vpaddq ($D3,$D3,$T1); # d3 += h1*r2 + &vpmuludq ($T0,$T2,&$addr(3)); # h1*r3 + &vpaddq ($D4,$D4,$T0); # d4 += h1*r3 + &vpmuludq ($T1,$T2,&$addr(8)); # h1*s4 + &vpaddq ($D0,$D0,$T1); # d0 += h1*s4 + &vmovdqa ($T1,&QWP(32*3,"esp")); # h3 + &vpmuludq ($T0,$T2,&$addr(0)); # h1*r0 + &vpaddq ($D1,$D1,$T0); # d1 += h1*r0 + &vpmuludq ($T2,$T2,&$addr(1)); # h1*r1 + &vpaddq ($D2,$D2,$T2); # d2 += h1*r1 + + &vpmuludq ($T0,$T1,&$addr(0)); # h3*r0 + &vpaddq ($D3,$D3,$T0); # d3 += h3*r0 + &vpmuludq ($T2,$T1,&$addr(1)); # h3*r1 + &vpaddq ($D4,$D4,$T2); # d4 += h3*r1 + &vpmuludq ($T0,$T1,&$addr(6)); # h3*s2 + &vpaddq ($D0,$D0,$T0); # d0 += h3*s2 + &vmovdqa ($T0,&QWP(32*4,"esp")); # h4 + &vpmuludq ($T2,$T1,&$addr(7)); # h3*s3 + &vpaddq ($D1,$D1,$T2); # d1+= h3*s3 + &vpmuludq ($T1,$T1,&$addr(8)); # h3*s4 + &vpaddq ($D2,$D2,$T1); # d2 += h3*s4 + + &vpmuludq ($T2,$T0,&$addr(8)); # h4*s4 + &vpaddq ($D3,$D3,$T2); # d3 += h4*s4 + &vpmuludq ($T1,$T0,&$addr(5)); # h4*s1 + &vpaddq ($D0,$D0,$T1); # d0 += h4*s1 + &vpmuludq ($T2,$T0,&$addr(0)); # h4*r0 + &vpaddq ($D4,$D4,$T2); # d4 += h4*r0 + &vmovdqa ($MASK,&QWP(64,"ebx")); + &vpmuludq ($T1,$T0,&$addr(6)); # h4*s2 + &vpaddq ($D1,$D1,$T1); # d1 += h4*s2 + &vpmuludq ($T0,$T0,&$addr(7)); # h4*s3 + &vpaddq ($D2,$D2,$T0); # d2 += h4*s3 +} + &vpmuladd (sub { my $i=shift; &QWP(32*$i-128,"edx"); }); + +sub vlazy_reduction { + ################################################################ + # lazy reduction + + &vpsrlq ($T0,$D3,26); + &vpand ($D3,$D3,$MASK); + &vpsrlq ($T1,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpaddq ($D4,$D4,$T0); # h3 -> h4 + &vpaddq ($D1,$D1,$T1); # h0 -> h1 + &vpsrlq ($T0,$D4,26); + &vpand ($D4,$D4,$MASK); + &vpsrlq ($T1,$D1,26); + &vpand ($D1,$D1,$MASK); + &vpaddq ($D2,$D2,$T1); # h1 -> h2 + &vpaddq ($D0,$D0,$T0); + &vpsllq ($T0,$T0,2); + &vpsrlq ($T1,$D2,26); + &vpand ($D2,$D2,$MASK); + &vpaddq ($D0,$D0,$T0); # h4 -> h0 + &vpaddq ($D3,$D3,$T1); # h2 -> h3 + &vpsrlq ($T1,$D3,26); + &vpsrlq ($T0,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpand ($D3,$D3,$MASK); + &vpaddq ($D1,$D1,$T0); # h0 -> h1 + &vpaddq ($D4,$D4,$T1); # h3 -> h4 +} + &vlazy_reduction(); + + &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1); + &lea ("esi",&DWP(16*4,"esi")); + &sub ("ecx",64); + &jnz (&label("loop")); + +&set_label("tail"); + &vsplat_input (); + &and ("ebx",-64); # restore pointer + + &vpmuladd (sub { my $i=shift; &QWP(4+32*$i-128,"edx"); }); + + ################################################################ + # horizontal addition + + &vpsrldq ($T0,$D4,8); + &vpsrldq ($T1,$D3,8); + &vpaddq ($D4,$D4,$T0); + &vpsrldq ($T0,$D0,8); + &vpaddq ($D3,$D3,$T1); + &vpsrldq ($T1,$D1,8); + &vpaddq ($D0,$D0,$T0); + &vpsrldq ($T0,$D2,8); + &vpaddq ($D1,$D1,$T1); + &vpermq ($T1,$D4,2); # keep folding + &vpaddq ($D2,$D2,$T0); + &vpermq ($T0,$D3,2); + &vpaddq ($D4,$D4,$T1); + &vpermq ($T1,$D0,2); + &vpaddq ($D3,$D3,$T0); + &vpermq ($T0,$D1,2); + &vpaddq ($D0,$D0,$T1); + &vpermq ($T1,$D2,2); + &vpaddq ($D1,$D1,$T0); + &vpaddq ($D2,$D2,$T1); + + &vlazy_reduction(); + + &cmp ("ecx",0); + &je (&label("done")); + + ################################################################ + # clear all but single word + + &vpshufd (&X($D0),&X($D0),0b11111100); + &lea ("edx",&DWP(32*5+128,"esp")); # restore pointer + &vpshufd (&X($D1),&X($D1),0b11111100); + &vpshufd (&X($D2),&X($D2),0b11111100); + &vpshufd (&X($D3),&X($D3),0b11111100); + &vpshufd (&X($D4),&X($D4),0b11111100); + &jmp (&label("even")); + +&set_label("done",16); + &vmovd (&DWP(-16*3+4*0,"edi"),&X($D0));# store hash value + &vmovd (&DWP(-16*3+4*1,"edi"),&X($D1)); + &vmovd (&DWP(-16*3+4*2,"edi"),&X($D2)); + &vmovd (&DWP(-16*3+4*3,"edi"),&X($D3)); + &vmovd (&DWP(-16*3+4*4,"edi"),&X($D4)); + &vzeroupper (); + &mov ("esp","ebp"); +&set_label("nodata"); +&function_end("_poly1305_blocks_avx2"); +} +&set_label("const_sse2",64); + &data_word(1<<24,0, 1<<24,0, 1<<24,0, 1<<24,0); + &data_word(0,0, 0,0, 0,0, 0,0); + &data_word(0x03ffffff,0,0x03ffffff,0, 0x03ffffff,0, 0x03ffffff,0); + &data_word(0x0fffffff,0x0ffffffc,0x0ffffffc,0x0ffffffc); +} +&asciz ("Poly1305 for x86, CRYPTOGAMS by "); +&align (4); + +&asm_finish(); diff --git a/external/boringssl/crypto/poly1305/asm/poly1305-x86_64.pl b/external/boringssl/crypto/poly1305/asm/poly1305-x86_64.pl new file mode 100755 index 0000000000..3c810c5a00 --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-x86_64.pl @@ -0,0 +1,2235 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 Poly1305 hash for x86_64. +# +# March 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# measured with rdtsc at fixed clock frequency. +# +# IALU/gcc-4.8(*) AVX(**) AVX2 +# P4 4.90/+120% - +# Core 2 2.39/+90% - +# Westmere 1.86/+120% - +# Sandy Bridge 1.39/+140% 1.10 +# Haswell 1.10/+175% 1.11 0.65 +# Skylake 1.12/+120% 0.96 0.51 +# Silvermont 2.83/+95% - +# VIA Nano 1.82/+150% - +# Sledgehammer 1.38/+160% - +# Bulldozer 2.21/+130% 0.97 +# +# (*) improvement coefficients relative to clang are more modest and +# are ~50% on most processors, in both cases we are comparing to +# __int128 code; +# (**) SSE2 implementation was attempted, but among non-AVX processors +# it was faster than integer-only code only on older Intel P4 and +# Core processors, 50-30%, less newer processor is, but slower on +# contemporary ones, for example almost 2x slower on Atom, and as +# former are naturally disappearing, SSE2 is deemed unnecessary; + +$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"; + +$avx = 2; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my ($ctx,$inp,$len,$padbit)=("%rdi","%rsi","%rdx","%rcx"); +my ($mac,$nonce)=($inp,$len); # *_emit arguments +my ($d1,$d2,$d3, $r0,$r1,$s1)=map("%r$_",(8..13)); +my ($h0,$h1,$h2)=("%r14","%rbx","%rbp"); + +sub poly1305_iteration { +# input: copy of $r1 in %rax, $h0-$h2, $r0-$r1 +# output: $h0-$h2 *= $r0-$r1 +$code.=<<___; + mulq $h0 # h0*r1 + mov %rax,$d2 + mov $r0,%rax + mov %rdx,$d3 + + mulq $h0 # h0*r0 + mov %rax,$h0 # future $h0 + mov $r0,%rax + mov %rdx,$d1 + + mulq $h1 # h1*r0 + add %rax,$d2 + mov $s1,%rax + adc %rdx,$d3 + + mulq $h1 # h1*s1 + mov $h2,$h1 # borrow $h1 + add %rax,$h0 + adc %rdx,$d1 + + imulq $s1,$h1 # h2*s1 + add $h1,$d2 + mov $d1,$h1 + adc \$0,$d3 + + imulq $r0,$h2 # h2*r0 + add $d2,$h1 + mov \$-4,%rax # mask value + adc $h2,$d3 + + and $d3,%rax # last reduction step + mov $d3,$h2 + shr \$2,$d3 + and \$3,$h2 + add $d3,%rax + add %rax,$h0 + adc \$0,$h1 +___ +} + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int64 h[3]; # current hash value base 2^64 +# unsigned __int64 r[2]; # key value base 2^64 + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl poly1305_init +.globl poly1305_blocks +.globl poly1305_emit +.type poly1305_init,\@function,3 +.align 32 +poly1305_init: + xor %rax,%rax + mov %rax,0($ctx) # initialize hash value + mov %rax,8($ctx) + mov %rax,16($ctx) + + cmp \$0,$inp + je .Lno_key + + lea poly1305_blocks(%rip),%r10 + lea poly1305_emit(%rip),%r11 +___ +$code.=<<___ if ($avx); + mov OPENSSL_ia32cap_P+4(%rip),%r9 + lea poly1305_blocks_avx(%rip),%rax + lea poly1305_emit_avx(%rip),%rcx + bt \$`60-32`,%r9 # AVX? + cmovc %rax,%r10 + cmovc %rcx,%r11 +___ +$code.=<<___ if ($avx>1); + lea poly1305_blocks_avx2(%rip),%rax + bt \$`5+32`,%r9 # AVX2? + cmovc %rax,%r10 +___ +$code.=<<___; + mov \$0x0ffffffc0fffffff,%rax + mov \$0x0ffffffc0ffffffc,%rcx + and 0($inp),%rax + and 8($inp),%rcx + mov %rax,24($ctx) + mov %rcx,32($ctx) +___ +$code.=<<___ if ($flavour !~ /elf32/); + mov %r10,0(%rdx) + mov %r11,8(%rdx) +___ +$code.=<<___ if ($flavour =~ /elf32/); + mov %r10d,0(%rdx) + mov %r11d,4(%rdx) +___ +$code.=<<___; + mov \$1,%eax +.Lno_key: + ret +.size poly1305_init,.-poly1305_init + +.type poly1305_blocks,\@function,4 +.align 32 +poly1305_blocks: +.Lblocks: + sub \$16,$len # too short? + jc .Lno_data + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lblocks_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2 + + mov $s1,$r1 + shr \$2,$s1 + mov $r1,%rax + add $r1,$s1 # s1 = r1 + (r1 >> 2) + jmp .Loop + +.align 32 +.Loop: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 +___ + &poly1305_iteration(); +$code.=<<___; + mov $r1,%rax + sub \$16,%r15 # len-=16 + jnc .Loop + + mov $h0,0($ctx) # store hash value + mov $h1,8($ctx) + mov $h2,16($ctx) + + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rsp +.Lno_data: +.Lblocks_epilogue: + ret +.size poly1305_blocks,.-poly1305_blocks + +.type poly1305_emit,\@function,3 +.align 32 +poly1305_emit: +.Lemit: + mov 0($ctx),%r8 # load hash value + mov 8($ctx),%r9 + mov 16($ctx),%r10 + + mov %r8,%rax + add \$5,%r8 # compare to modulus + mov %r9,%rcx + adc \$0,%r9 + adc \$0,%r10 + shr \$2,%r10 # did 130-bit value overfow? + cmovnz %r8,%rax + cmovnz %r9,%rcx + + add 0($nonce),%rax # accumulate nonce + adc 8($nonce),%rcx + mov %rax,0($mac) # write result + mov %rcx,8($mac) + + ret +.size poly1305_emit,.-poly1305_emit +___ +if ($avx) { + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^26 +# unsigned __int32 is_base2_26; +# unsigned __int64 r[2]; # key value base 2^64 +# unsigned __int64 pad; +# struct { unsigned __int32 r^2, r^1, r^4, r^3; } r[9]; +# +# where r^n are base 2^26 digits of degrees of multiplier key. There are +# 5 digits, but last four are interleaved with multiples of 5, totalling +# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4. + +my ($H0,$H1,$H2,$H3,$H4, $T0,$T1,$T2,$T3,$T4, $D0,$D1,$D2,$D3,$D4, $MASK) = + map("%xmm$_",(0..15)); + +$code.=<<___; +.type __poly1305_block,\@abi-omnipotent +.align 32 +__poly1305_block: +___ + &poly1305_iteration(); +$code.=<<___; + ret +.size __poly1305_block,.-__poly1305_block + +.type __poly1305_init_avx,\@abi-omnipotent +.align 32 +__poly1305_init_avx: + mov $r0,$h0 + mov $r1,$h1 + xor $h2,$h2 + + lea 48+64($ctx),$ctx # size optimization + + mov $r1,%rax + call __poly1305_block # r^2 + + mov \$0x3ffffff,%eax # save interleaved r^2 and r base 2^26 + mov \$0x3ffffff,%edx + mov $h0,$d1 + and $h0#d,%eax + mov $r0,$d2 + and $r0#d,%edx + mov %eax,`16*0+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*0+4-64`($ctx) + shr \$26,$d2 + + mov \$0x3ffffff,%eax + mov \$0x3ffffff,%edx + and $d1#d,%eax + and $d2#d,%edx + mov %eax,`16*1+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*1+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*2+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*2+4-64`($ctx) + shr \$26,$d2 + + mov $h1,%rax + mov $r1,%rdx + shl \$12,%rax + shl \$12,%rdx + or $d1,%rax + or $d2,%rdx + and \$0x3ffffff,%eax + and \$0x3ffffff,%edx + mov %eax,`16*3+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*3+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*4+0-64`($ctx) + mov $h1,$d1 + mov %edx,`16*4+4-64`($ctx) + mov $r1,$d2 + + mov \$0x3ffffff,%eax + mov \$0x3ffffff,%edx + shr \$14,$d1 + shr \$14,$d2 + and $d1#d,%eax + and $d2#d,%edx + mov %eax,`16*5+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*5+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*6+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*6+4-64`($ctx) + shr \$26,$d2 + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+0-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d2#d,`16*7+4-64`($ctx) + lea ($d2,$d2,4),$d2 # *5 + mov $d1#d,`16*8+0-64`($ctx) + mov $d2#d,`16*8+4-64`($ctx) + + mov $r1,%rax + call __poly1305_block # r^3 + + mov \$0x3ffffff,%eax # save r^3 base 2^26 + mov $h0,$d1 + and $h0#d,%eax + shr \$26,$d1 + mov %eax,`16*0+12-64`($ctx) + + mov \$0x3ffffff,%edx + and $d1#d,%edx + mov %edx,`16*1+12-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*2+12-64`($ctx) + + mov $h1,%rax + shl \$12,%rax + or $d1,%rax + and \$0x3ffffff,%eax + mov %eax,`16*3+12-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov $h1,$d1 + mov %eax,`16*4+12-64`($ctx) + + mov \$0x3ffffff,%edx + shr \$14,$d1 + and $d1#d,%edx + mov %edx,`16*5+12-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*6+12-64`($ctx) + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+12-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d1#d,`16*8+12-64`($ctx) + + mov $r1,%rax + call __poly1305_block # r^4 + + mov \$0x3ffffff,%eax # save r^4 base 2^26 + mov $h0,$d1 + and $h0#d,%eax + shr \$26,$d1 + mov %eax,`16*0+8-64`($ctx) + + mov \$0x3ffffff,%edx + and $d1#d,%edx + mov %edx,`16*1+8-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*2+8-64`($ctx) + + mov $h1,%rax + shl \$12,%rax + or $d1,%rax + and \$0x3ffffff,%eax + mov %eax,`16*3+8-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov $h1,$d1 + mov %eax,`16*4+8-64`($ctx) + + mov \$0x3ffffff,%edx + shr \$14,$d1 + and $d1#d,%edx + mov %edx,`16*5+8-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*6+8-64`($ctx) + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+8-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d1#d,`16*8+8-64`($ctx) + + lea -48-64($ctx),$ctx # size [de-]optimization + ret +.size __poly1305_init_avx,.-__poly1305_init_avx + +.type poly1305_blocks_avx,\@function,4 +.align 32 +poly1305_blocks_avx: + mov 20($ctx),%r8d # is_base2_26 + cmp \$128,$len + jae .Lblocks_avx + test %r8d,%r8d + jz .Lblocks + +.Lblocks_avx: + and \$-16,$len + jz .Lno_data_avx + + vzeroupper + + test %r8d,%r8d + jz .Lbase2_64_avx + + test \$31,$len + jz .Leven_avx + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lblocks_avx_body: + + mov $len,%r15 # reassign $len + + mov 0($ctx),$d1 # load hash value + mov 8($ctx),$d2 + mov 16($ctx),$h2#d + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + ################################# base 2^26 -> base 2^64 + mov $d1#d,$h0#d + and \$-1<<31,$d1 + mov $d2,$r1 # borrow $r1 + mov $d2#d,$h1#d + and \$-1<<31,$d2 + + shr \$6,$d1 + shl \$52,$r1 + add $d1,$h0 + shr \$12,$h1 + shr \$18,$d2 + add $r1,$h0 + adc $d2,$h1 + + mov $h2,$d1 + shl \$40,$d1 + shr \$24,$h2 + add $d1,$h1 + adc \$0,$h2 # can be partially reduced... + + mov \$-4,$d2 # ... so reduce + mov $h2,$d1 + and $h2,$d2 + shr \$2,$d1 + and \$3,$h2 + add $d2,$d1 # =*5 + add $d1,$h0 + adc \$0,$h1 + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + + call __poly1305_block + + test $padbit,$padbit # if $padbit is zero, + jz .Lstore_base2_64_avx # store hash in base 2^64 format + + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$r0 + mov $h1,$r1 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$r0 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $r0,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$r1 + and \$0x3ffffff,$h1 # h[3] + or $r1,$h2 # h[4] + + sub \$16,%r15 + jz .Lstore_base2_26_avx + + vmovd %rax#d,$H0 + vmovd %rdx#d,$H1 + vmovd $h0#d,$H2 + vmovd $h1#d,$H3 + vmovd $h2#d,$H4 + jmp .Lproceed_avx + +.align 32 +.Lstore_base2_64_avx: + mov $h0,0($ctx) + mov $h1,8($ctx) + mov $h2,16($ctx) # note that is_base2_26 is zeroed + jmp .Ldone_avx + +.align 16 +.Lstore_base2_26_avx: + mov %rax#d,0($ctx) # store hash value base 2^26 + mov %rdx#d,4($ctx) + mov $h0#d,8($ctx) + mov $h1#d,12($ctx) + mov $h2#d,16($ctx) +.align 16 +.Ldone_avx: + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rsp +.Lno_data_avx: +.Lblocks_avx_epilogue: + ret + +.align 32 +.Lbase2_64_avx: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lbase2_64_avx_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2#d + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + test \$31,$len + jz .Linit_avx + + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + +.Linit_avx: + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$d1 + mov $h1,$d2 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$d1 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $d1,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$d2 + and \$0x3ffffff,$h1 # h[3] + or $d2,$h2 # h[4] + + vmovd %rax#d,$H0 + vmovd %rdx#d,$H1 + vmovd $h0#d,$H2 + vmovd $h1#d,$H3 + vmovd $h2#d,$H4 + movl \$1,20($ctx) # set is_base2_26 + + call __poly1305_init_avx + +.Lproceed_avx: + mov %r15,$len + + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rax + lea 48(%rsp),%rsp +.Lbase2_64_avx_epilogue: + jmp .Ldo_avx + +.align 32 +.Leven_avx: + vmovd 4*0($ctx),$H0 # load hash value + vmovd 4*1($ctx),$H1 + vmovd 4*2($ctx),$H2 + vmovd 4*3($ctx),$H3 + vmovd 4*4($ctx),$H4 + +.Ldo_avx: +___ +$code.=<<___ if (!$win64); + lea -0x58(%rsp),%r11 + sub \$0x178,%rsp +___ +$code.=<<___ if ($win64); + lea -0xf8(%rsp),%r11 + sub \$0x218,%rsp + vmovdqa %xmm6,0x50(%r11) + vmovdqa %xmm7,0x60(%r11) + vmovdqa %xmm8,0x70(%r11) + vmovdqa %xmm9,0x80(%r11) + vmovdqa %xmm10,0x90(%r11) + vmovdqa %xmm11,0xa0(%r11) + vmovdqa %xmm12,0xb0(%r11) + vmovdqa %xmm13,0xc0(%r11) + vmovdqa %xmm14,0xd0(%r11) + vmovdqa %xmm15,0xe0(%r11) +.Ldo_avx_body: +___ +$code.=<<___; + sub \$64,$len + lea -32($inp),%rax + cmovc %rax,$inp + + vmovdqu `16*3`($ctx),$D4 # preload r0^2 + lea `16*3+64`($ctx),$ctx # size optimization + lea .Lconst(%rip),%rcx + + ################################################################ + # load input + vmovdqu 16*2($inp),$T0 + vmovdqu 16*3($inp),$T1 + vmovdqa 64(%rcx),$MASK # .Lmask26 + + vpsrldq \$6,$T0,$T2 # splat input + vpsrldq \$6,$T1,$T3 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + + vpsrlq \$40,$T4,$T4 # 4 + vpsrlq \$26,$T0,$T1 + vpand $MASK,$T0,$T0 # 0 + vpsrlq \$4,$T3,$T2 + vpand $MASK,$T1,$T1 # 1 + vpsrlq \$30,$T3,$T3 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + jbe .Lskip_loop_avx + + # expand and copy pre-calculated table to stack + vmovdqu `16*1-64`($ctx),$D1 + vmovdqu `16*2-64`($ctx),$D2 + vpshufd \$0xEE,$D4,$D3 # 34xx -> 3434 + vpshufd \$0x44,$D4,$D0 # xx12 -> 1212 + vmovdqa $D3,-0x90(%r11) + vmovdqa $D0,0x00(%rsp) + vpshufd \$0xEE,$D1,$D4 + vmovdqu `16*3-64`($ctx),$D0 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D4,-0x80(%r11) + vmovdqa $D1,0x10(%rsp) + vpshufd \$0xEE,$D2,$D3 + vmovdqu `16*4-64`($ctx),$D1 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D3,-0x70(%r11) + vmovdqa $D2,0x20(%rsp) + vpshufd \$0xEE,$D0,$D4 + vmovdqu `16*5-64`($ctx),$D2 + vpshufd \$0x44,$D0,$D0 + vmovdqa $D4,-0x60(%r11) + vmovdqa $D0,0x30(%rsp) + vpshufd \$0xEE,$D1,$D3 + vmovdqu `16*6-64`($ctx),$D0 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D3,-0x50(%r11) + vmovdqa $D1,0x40(%rsp) + vpshufd \$0xEE,$D2,$D4 + vmovdqu `16*7-64`($ctx),$D1 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D4,-0x40(%r11) + vmovdqa $D2,0x50(%rsp) + vpshufd \$0xEE,$D0,$D3 + vmovdqu `16*8-64`($ctx),$D2 + vpshufd \$0x44,$D0,$D0 + vmovdqa $D3,-0x30(%r11) + vmovdqa $D0,0x60(%rsp) + vpshufd \$0xEE,$D1,$D4 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D4,-0x20(%r11) + vmovdqa $D1,0x70(%rsp) + vpshufd \$0xEE,$D2,$D3 + vmovdqa 0x00(%rsp),$D4 # preload r0^2 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D3,-0x10(%r11) + vmovdqa $D2,0x80(%rsp) + + jmp .Loop_avx + +.align 32 +.Loop_avx: + ################################################################ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + # \___________________/ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + # \___________________/ \____________________/ + # + # Note that we start with inp[2:3]*r^2. This is because it + # doesn't depend on reduction in previous iteration. + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + # + # though note that $Tx and $Hx are "reversed" in this section, + # and $D4 is preloaded with r0^2... + + vpmuludq $T0,$D4,$D0 # d0 = h0*r0 + vpmuludq $T1,$D4,$D1 # d1 = h1*r0 + vmovdqa $H2,0x20(%r11) # offload hash + vpmuludq $T2,$D4,$D2 # d3 = h2*r0 + vmovdqa 0x10(%rsp),$H2 # r1^2 + vpmuludq $T3,$D4,$D3 # d3 = h3*r0 + vpmuludq $T4,$D4,$D4 # d4 = h4*r0 + + vmovdqa $H0,0x00(%r11) # + vpmuludq 0x20(%rsp),$T4,$H0 # h4*s1 + vmovdqa $H1,0x10(%r11) # + vpmuludq $T3,$H2,$H1 # h3*r1 + vpaddq $H0,$D0,$D0 # d0 += h4*s1 + vpaddq $H1,$D4,$D4 # d4 += h3*r1 + vmovdqa $H3,0x30(%r11) # + vpmuludq $T2,$H2,$H0 # h2*r1 + vpmuludq $T1,$H2,$H1 # h1*r1 + vpaddq $H0,$D3,$D3 # d3 += h2*r1 + vmovdqa 0x30(%rsp),$H3 # r2^2 + vpaddq $H1,$D2,$D2 # d2 += h1*r1 + vmovdqa $H4,0x40(%r11) # + vpmuludq $T0,$H2,$H2 # h0*r1 + vpmuludq $T2,$H3,$H0 # h2*r2 + vpaddq $H2,$D1,$D1 # d1 += h0*r1 + + vmovdqa 0x40(%rsp),$H4 # s2^2 + vpaddq $H0,$D4,$D4 # d4 += h2*r2 + vpmuludq $T1,$H3,$H1 # h1*r2 + vpmuludq $T0,$H3,$H3 # h0*r2 + vpaddq $H1,$D3,$D3 # d3 += h1*r2 + vmovdqa 0x50(%rsp),$H2 # r3^2 + vpaddq $H3,$D2,$D2 # d2 += h0*r2 + vpmuludq $T4,$H4,$H0 # h4*s2 + vpmuludq $T3,$H4,$H4 # h3*s2 + vpaddq $H0,$D1,$D1 # d1 += h4*s2 + vmovdqa 0x60(%rsp),$H3 # s3^2 + vpaddq $H4,$D0,$D0 # d0 += h3*s2 + + vmovdqa 0x80(%rsp),$H4 # s4^2 + vpmuludq $T1,$H2,$H1 # h1*r3 + vpmuludq $T0,$H2,$H2 # h0*r3 + vpaddq $H1,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $T4,$H3,$H0 # h4*s3 + vpmuludq $T3,$H3,$H1 # h3*s3 + vpaddq $H0,$D2,$D2 # d2 += h4*s3 + vmovdqu 16*0($inp),$H0 # load input + vpaddq $H1,$D1,$D1 # d1 += h3*s3 + vpmuludq $T2,$H3,$H3 # h2*s3 + vpmuludq $T2,$H4,$T2 # h2*s4 + vpaddq $H3,$D0,$D0 # d0 += h2*s3 + + vmovdqu 16*1($inp),$H1 # + vpaddq $T2,$D1,$D1 # d1 += h2*s4 + vpmuludq $T3,$H4,$T3 # h3*s4 + vpmuludq $T4,$H4,$T4 # h4*s4 + vpsrldq \$6,$H0,$H2 # splat input + vpaddq $T3,$D2,$D2 # d2 += h3*s4 + vpaddq $T4,$D3,$D3 # d3 += h4*s4 + vpsrldq \$6,$H1,$H3 # + vpmuludq 0x70(%rsp),$T0,$T4 # h0*r4 + vpmuludq $T1,$H4,$T0 # h1*s4 + vpunpckhqdq $H1,$H0,$H4 # 4 + vpaddq $T4,$D4,$D4 # d4 += h0*r4 + vmovdqa -0x90(%r11),$T4 # r0^4 + vpaddq $T0,$D0,$D0 # d0 += h1*s4 + + vpunpcklqdq $H1,$H0,$H0 # 0:1 + vpunpcklqdq $H3,$H2,$H3 # 2:3 + + #vpsrlq \$40,$H4,$H4 # 4 + vpsrldq \$`40/8`,$H4,$H4 # 4 + vpsrlq \$26,$H0,$H1 + vpand $MASK,$H0,$H0 # 0 + vpsrlq \$4,$H3,$H2 + vpand $MASK,$H1,$H1 # 1 + vpand 0(%rcx),$H4,$H4 # .Lmask24 + vpsrlq \$30,$H3,$H3 + vpand $MASK,$H2,$H2 # 2 + vpand $MASK,$H3,$H3 # 3 + vpor 32(%rcx),$H4,$H4 # padbit, yes, always + + vpaddq 0x00(%r11),$H0,$H0 # add hash value + vpaddq 0x10(%r11),$H1,$H1 + vpaddq 0x20(%r11),$H2,$H2 + vpaddq 0x30(%r11),$H3,$H3 + vpaddq 0x40(%r11),$H4,$H4 + + lea 16*2($inp),%rax + lea 16*4($inp),$inp + sub \$64,$len + cmovc %rax,$inp + + ################################################################ + # Now we accumulate (inp[0:1]+hash)*r^4 + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + vpmuludq $H0,$T4,$T0 # h0*r0 + vpmuludq $H1,$T4,$T1 # h1*r0 + vpaddq $T0,$D0,$D0 + vpaddq $T1,$D1,$D1 + vmovdqa -0x80(%r11),$T2 # r1^4 + vpmuludq $H2,$T4,$T0 # h2*r0 + vpmuludq $H3,$T4,$T1 # h3*r0 + vpaddq $T0,$D2,$D2 + vpaddq $T1,$D3,$D3 + vpmuludq $H4,$T4,$T4 # h4*r0 + vpmuludq -0x70(%r11),$H4,$T0 # h4*s1 + vpaddq $T4,$D4,$D4 + + vpaddq $T0,$D0,$D0 # d0 += h4*s1 + vpmuludq $H2,$T2,$T1 # h2*r1 + vpmuludq $H3,$T2,$T0 # h3*r1 + vpaddq $T1,$D3,$D3 # d3 += h2*r1 + vmovdqa -0x60(%r11),$T3 # r2^4 + vpaddq $T0,$D4,$D4 # d4 += h3*r1 + vpmuludq $H1,$T2,$T1 # h1*r1 + vpmuludq $H0,$T2,$T2 # h0*r1 + vpaddq $T1,$D2,$D2 # d2 += h1*r1 + vpaddq $T2,$D1,$D1 # d1 += h0*r1 + + vmovdqa -0x50(%r11),$T4 # s2^4 + vpmuludq $H2,$T3,$T0 # h2*r2 + vpmuludq $H1,$T3,$T1 # h1*r2 + vpaddq $T0,$D4,$D4 # d4 += h2*r2 + vpaddq $T1,$D3,$D3 # d3 += h1*r2 + vmovdqa -0x40(%r11),$T2 # r3^4 + vpmuludq $H0,$T3,$T3 # h0*r2 + vpmuludq $H4,$T4,$T0 # h4*s2 + vpaddq $T3,$D2,$D2 # d2 += h0*r2 + vpaddq $T0,$D1,$D1 # d1 += h4*s2 + vmovdqa -0x30(%r11),$T3 # s3^4 + vpmuludq $H3,$T4,$T4 # h3*s2 + vpmuludq $H1,$T2,$T1 # h1*r3 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + + vmovdqa -0x10(%r11),$T4 # s4^4 + vpaddq $T1,$D4,$D4 # d4 += h1*r3 + vpmuludq $H0,$T2,$T2 # h0*r3 + vpmuludq $H4,$T3,$T0 # h4*s3 + vpaddq $T2,$D3,$D3 # d3 += h0*r3 + vpaddq $T0,$D2,$D2 # d2 += h4*s3 + vmovdqu 16*2($inp),$T0 # load input + vpmuludq $H3,$T3,$T2 # h3*s3 + vpmuludq $H2,$T3,$T3 # h2*s3 + vpaddq $T2,$D1,$D1 # d1 += h3*s3 + vmovdqu 16*3($inp),$T1 # + vpaddq $T3,$D0,$D0 # d0 += h2*s3 + + vpmuludq $H2,$T4,$H2 # h2*s4 + vpmuludq $H3,$T4,$H3 # h3*s4 + vpsrldq \$6,$T0,$T2 # splat input + vpaddq $H2,$D1,$D1 # d1 += h2*s4 + vpmuludq $H4,$T4,$H4 # h4*s4 + vpsrldq \$6,$T1,$T3 # + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*s4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*s4 + vpmuludq -0x20(%r11),$H0,$H4 # h0*r4 + vpmuludq $H1,$T4,$H0 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + + #vpsrlq \$40,$T4,$T4 # 4 + vpsrldq \$`40/8`,$T4,$T4 # 4 + vpsrlq \$26,$T0,$T1 + vmovdqa 0x00(%rsp),$D4 # preload r0^2 + vpand $MASK,$T0,$T0 # 0 + vpsrlq \$4,$T3,$T2 + vpand $MASK,$T1,$T1 # 1 + vpand 0(%rcx),$T4,$T4 # .Lmask24 + vpsrlq \$30,$T3,$T3 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + ################################################################ + # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + # and P. Schwabe + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D0 + vpand $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D0,$H0,$H0 + vpsllq \$2,$D0,$D0 + vpaddq $D0,$H0,$H0 # h4 -> h0 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + ja .Loop_avx + +.Lskip_loop_avx: + ################################################################ + # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + vpshufd \$0x10,$D4,$D4 # r0^n, xx12 -> x1x2 + add \$32,$len + jnz .Long_tail_avx + + vpaddq $H2,$T2,$T2 + vpaddq $H0,$T0,$T0 + vpaddq $H1,$T1,$T1 + vpaddq $H3,$T3,$T3 + vpaddq $H4,$T4,$T4 + +.Long_tail_avx: + vmovdqa $H2,0x20(%r11) + vmovdqa $H0,0x00(%r11) + vmovdqa $H1,0x10(%r11) + vmovdqa $H3,0x30(%r11) + vmovdqa $H4,0x40(%r11) + + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + vpmuludq $T2,$D4,$D2 # d2 = h2*r0 + vpmuludq $T0,$D4,$D0 # d0 = h0*r0 + vpshufd \$0x10,`16*1-64`($ctx),$H2 # r1^n + vpmuludq $T1,$D4,$D1 # d1 = h1*r0 + vpmuludq $T3,$D4,$D3 # d3 = h3*r0 + vpmuludq $T4,$D4,$D4 # d4 = h4*r0 + + vpmuludq $T3,$H2,$H0 # h3*r1 + vpaddq $H0,$D4,$D4 # d4 += h3*r1 + vpshufd \$0x10,`16*2-64`($ctx),$H3 # s1^n + vpmuludq $T2,$H2,$H1 # h2*r1 + vpaddq $H1,$D3,$D3 # d3 += h2*r1 + vpshufd \$0x10,`16*3-64`($ctx),$H4 # r2^n + vpmuludq $T1,$H2,$H0 # h1*r1 + vpaddq $H0,$D2,$D2 # d2 += h1*r1 + vpmuludq $T0,$H2,$H2 # h0*r1 + vpaddq $H2,$D1,$D1 # d1 += h0*r1 + vpmuludq $T4,$H3,$H3 # h4*s1 + vpaddq $H3,$D0,$D0 # d0 += h4*s1 + + vpshufd \$0x10,`16*4-64`($ctx),$H2 # s2^n + vpmuludq $T2,$H4,$H1 # h2*r2 + vpaddq $H1,$D4,$D4 # d4 += h2*r2 + vpmuludq $T1,$H4,$H0 # h1*r2 + vpaddq $H0,$D3,$D3 # d3 += h1*r2 + vpshufd \$0x10,`16*5-64`($ctx),$H3 # r3^n + vpmuludq $T0,$H4,$H4 # h0*r2 + vpaddq $H4,$D2,$D2 # d2 += h0*r2 + vpmuludq $T4,$H2,$H1 # h4*s2 + vpaddq $H1,$D1,$D1 # d1 += h4*s2 + vpshufd \$0x10,`16*6-64`($ctx),$H4 # s3^n + vpmuludq $T3,$H2,$H2 # h3*s2 + vpaddq $H2,$D0,$D0 # d0 += h3*s2 + + vpmuludq $T1,$H3,$H0 # h1*r3 + vpaddq $H0,$D4,$D4 # d4 += h1*r3 + vpmuludq $T0,$H3,$H3 # h0*r3 + vpaddq $H3,$D3,$D3 # d3 += h0*r3 + vpshufd \$0x10,`16*7-64`($ctx),$H2 # r4^n + vpmuludq $T4,$H4,$H1 # h4*s3 + vpaddq $H1,$D2,$D2 # d2 += h4*s3 + vpshufd \$0x10,`16*8-64`($ctx),$H3 # s4^n + vpmuludq $T3,$H4,$H0 # h3*s3 + vpaddq $H0,$D1,$D1 # d1 += h3*s3 + vpmuludq $T2,$H4,$H4 # h2*s3 + vpaddq $H4,$D0,$D0 # d0 += h2*s3 + + vpmuludq $T0,$H2,$H2 # h0*r4 + vpaddq $H2,$D4,$D4 # h4 = d4 + h0*r4 + vpmuludq $T4,$H3,$H1 # h4*s4 + vpaddq $H1,$D3,$D3 # h3 = d3 + h4*s4 + vpmuludq $T3,$H3,$H0 # h3*s4 + vpaddq $H0,$D2,$D2 # h2 = d2 + h3*s4 + vpmuludq $T2,$H3,$H1 # h2*s4 + vpaddq $H1,$D1,$D1 # h1 = d1 + h2*s4 + vpmuludq $T1,$H3,$H3 # h1*s4 + vpaddq $H3,$D0,$D0 # h0 = d0 + h1*s4 + + jz .Lshort_tail_avx + + vmovdqu 16*0($inp),$H0 # load input + vmovdqu 16*1($inp),$H1 + + vpsrldq \$6,$H0,$H2 # splat input + vpsrldq \$6,$H1,$H3 + vpunpckhqdq $H1,$H0,$H4 # 4 + vpunpcklqdq $H1,$H0,$H0 # 0:1 + vpunpcklqdq $H3,$H2,$H3 # 2:3 + + vpsrlq \$40,$H4,$H4 # 4 + vpsrlq \$26,$H0,$H1 + vpand $MASK,$H0,$H0 # 0 + vpsrlq \$4,$H3,$H2 + vpand $MASK,$H1,$H1 # 1 + vpsrlq \$30,$H3,$H3 + vpand $MASK,$H2,$H2 # 2 + vpand $MASK,$H3,$H3 # 3 + vpor 32(%rcx),$H4,$H4 # padbit, yes, always + + vpshufd \$0x32,`16*0-64`($ctx),$T4 # r0^n, 34xx -> x3x4 + vpaddq 0x00(%r11),$H0,$H0 + vpaddq 0x10(%r11),$H1,$H1 + vpaddq 0x20(%r11),$H2,$H2 + vpaddq 0x30(%r11),$H3,$H3 + vpaddq 0x40(%r11),$H4,$H4 + + ################################################################ + # multiply (inp[0:1]+hash) by r^4:r^3 and accumulate + + vpmuludq $H0,$T4,$T0 # h0*r0 + vpaddq $T0,$D0,$D0 # d0 += h0*r0 + vpmuludq $H1,$T4,$T1 # h1*r0 + vpaddq $T1,$D1,$D1 # d1 += h1*r0 + vpmuludq $H2,$T4,$T0 # h2*r0 + vpaddq $T0,$D2,$D2 # d2 += h2*r0 + vpshufd \$0x32,`16*1-64`($ctx),$T2 # r1^n + vpmuludq $H3,$T4,$T1 # h3*r0 + vpaddq $T1,$D3,$D3 # d3 += h3*r0 + vpmuludq $H4,$T4,$T4 # h4*r0 + vpaddq $T4,$D4,$D4 # d4 += h4*r0 + + vpmuludq $H3,$T2,$T0 # h3*r1 + vpaddq $T0,$D4,$D4 # d4 += h3*r1 + vpshufd \$0x32,`16*2-64`($ctx),$T3 # s1 + vpmuludq $H2,$T2,$T1 # h2*r1 + vpaddq $T1,$D3,$D3 # d3 += h2*r1 + vpshufd \$0x32,`16*3-64`($ctx),$T4 # r2 + vpmuludq $H1,$T2,$T0 # h1*r1 + vpaddq $T0,$D2,$D2 # d2 += h1*r1 + vpmuludq $H0,$T2,$T2 # h0*r1 + vpaddq $T2,$D1,$D1 # d1 += h0*r1 + vpmuludq $H4,$T3,$T3 # h4*s1 + vpaddq $T3,$D0,$D0 # d0 += h4*s1 + + vpshufd \$0x32,`16*4-64`($ctx),$T2 # s2 + vpmuludq $H2,$T4,$T1 # h2*r2 + vpaddq $T1,$D4,$D4 # d4 += h2*r2 + vpmuludq $H1,$T4,$T0 # h1*r2 + vpaddq $T0,$D3,$D3 # d3 += h1*r2 + vpshufd \$0x32,`16*5-64`($ctx),$T3 # r3 + vpmuludq $H0,$T4,$T4 # h0*r2 + vpaddq $T4,$D2,$D2 # d2 += h0*r2 + vpmuludq $H4,$T2,$T1 # h4*s2 + vpaddq $T1,$D1,$D1 # d1 += h4*s2 + vpshufd \$0x32,`16*6-64`($ctx),$T4 # s3 + vpmuludq $H3,$T2,$T2 # h3*s2 + vpaddq $T2,$D0,$D0 # d0 += h3*s2 + + vpmuludq $H1,$T3,$T0 # h1*r3 + vpaddq $T0,$D4,$D4 # d4 += h1*r3 + vpmuludq $H0,$T3,$T3 # h0*r3 + vpaddq $T3,$D3,$D3 # d3 += h0*r3 + vpshufd \$0x32,`16*7-64`($ctx),$T2 # r4 + vpmuludq $H4,$T4,$T1 # h4*s3 + vpaddq $T1,$D2,$D2 # d2 += h4*s3 + vpshufd \$0x32,`16*8-64`($ctx),$T3 # s4 + vpmuludq $H3,$T4,$T0 # h3*s3 + vpaddq $T0,$D1,$D1 # d1 += h3*s3 + vpmuludq $H2,$T4,$T4 # h2*s3 + vpaddq $T4,$D0,$D0 # d0 += h2*s3 + + vpmuludq $H0,$T2,$T2 # h0*r4 + vpaddq $T2,$D4,$D4 # d4 += h0*r4 + vpmuludq $H4,$T3,$T1 # h4*s4 + vpaddq $T1,$D3,$D3 # d3 += h4*s4 + vpmuludq $H3,$T3,$T0 # h3*s4 + vpaddq $T0,$D2,$D2 # d2 += h3*s4 + vpmuludq $H2,$T3,$T1 # h2*s4 + vpaddq $T1,$D1,$D1 # d1 += h2*s4 + vpmuludq $H1,$T3,$T3 # h1*s4 + vpaddq $T3,$D0,$D0 # d0 += h1*s4 + +.Lshort_tail_avx: + ################################################################ + # horizontal addition + + vpsrldq \$8,$D4,$T4 + vpsrldq \$8,$D3,$T3 + vpsrldq \$8,$D1,$T1 + vpsrldq \$8,$D0,$T0 + vpsrldq \$8,$D2,$T2 + vpaddq $T3,$D3,$D3 + vpaddq $T4,$D4,$D4 + vpaddq $T0,$D0,$D0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$D2,$D2 + + ################################################################ + # lazy reduction + + vpsrlq \$26,$D3,$H3 + vpand $MASK,$D3,$D3 + vpaddq $H3,$D4,$D4 # h3 -> h4 + + vpsrlq \$26,$D0,$H0 + vpand $MASK,$D0,$D0 + vpaddq $H0,$D1,$D1 # h0 -> h1 + + vpsrlq \$26,$D4,$H4 + vpand $MASK,$D4,$D4 + + vpsrlq \$26,$D1,$H1 + vpand $MASK,$D1,$D1 + vpaddq $H1,$D2,$D2 # h1 -> h2 + + vpaddq $H4,$D0,$D0 + vpsllq \$2,$H4,$H4 + vpaddq $H4,$D0,$D0 # h4 -> h0 + + vpsrlq \$26,$D2,$H2 + vpand $MASK,$D2,$D2 + vpaddq $H2,$D3,$D3 # h2 -> h3 + + vpsrlq \$26,$D0,$H0 + vpand $MASK,$D0,$D0 + vpaddq $H0,$D1,$D1 # h0 -> h1 + + vpsrlq \$26,$D3,$H3 + vpand $MASK,$D3,$D3 + vpaddq $H3,$D4,$D4 # h3 -> h4 + + vmovd $D0,`4*0-48-64`($ctx) # save partially reduced + vmovd $D1,`4*1-48-64`($ctx) + vmovd $D2,`4*2-48-64`($ctx) + vmovd $D3,`4*3-48-64`($ctx) + vmovd $D4,`4*4-48-64`($ctx) +___ +$code.=<<___ if ($win64); + vmovdqa 0x50(%r11),%xmm6 + vmovdqa 0x60(%r11),%xmm7 + vmovdqa 0x70(%r11),%xmm8 + vmovdqa 0x80(%r11),%xmm9 + vmovdqa 0x90(%r11),%xmm10 + vmovdqa 0xa0(%r11),%xmm11 + vmovdqa 0xb0(%r11),%xmm12 + vmovdqa 0xc0(%r11),%xmm13 + vmovdqa 0xd0(%r11),%xmm14 + vmovdqa 0xe0(%r11),%xmm15 + lea 0xf8(%r11),%rsp +.Ldo_avx_epilogue: +___ +$code.=<<___ if (!$win64); + lea 0x58(%r11),%rsp +___ +$code.=<<___; + vzeroupper + ret +.size poly1305_blocks_avx,.-poly1305_blocks_avx + +.type poly1305_emit_avx,\@function,3 +.align 32 +poly1305_emit_avx: + cmpl \$0,20($ctx) # is_base2_26? + je .Lemit + + mov 0($ctx),%eax # load hash value base 2^26 + mov 4($ctx),%ecx + mov 8($ctx),%r8d + mov 12($ctx),%r11d + mov 16($ctx),%r10d + + shl \$26,%rcx # base 2^26 -> base 2^64 + mov %r8,%r9 + shl \$52,%r8 + add %rcx,%rax + shr \$12,%r9 + add %rax,%r8 # h0 + adc \$0,%r9 + + shl \$14,%r11 + mov %r10,%rax + shr \$24,%r10 + add %r11,%r9 + shl \$40,%rax + add %rax,%r9 # h1 + adc \$0,%r10 # h2 + + mov %r10,%rax # could be partially reduced, so reduce + mov %r10,%rcx + and \$3,%r10 + shr \$2,%rax + and \$-4,%rcx + add %rcx,%rax + add %rax,%r8 + adc \$0,%r9 + + mov %r8,%rax + add \$5,%r8 # compare to modulus + mov %r9,%rcx + adc \$0,%r9 + adc \$0,%r10 + shr \$2,%r10 # did 130-bit value overfow? + cmovnz %r8,%rax + cmovnz %r9,%rcx + + add 0($nonce),%rax # accumulate nonce + adc 8($nonce),%rcx + mov %rax,0($mac) # write result + mov %rcx,8($mac) + + ret +.size poly1305_emit_avx,.-poly1305_emit_avx +___ + +if ($avx>1) { +my ($H0,$H1,$H2,$H3,$H4, $MASK, $T4,$T0,$T1,$T2,$T3, $D0,$D1,$D2,$D3,$D4) = + map("%ymm$_",(0..15)); +my $S4=$MASK; + +$code.=<<___; +.type poly1305_blocks_avx2,\@function,4 +.align 32 +poly1305_blocks_avx2: + mov 20($ctx),%r8d # is_base2_26 + cmp \$128,$len + jae .Lblocks_avx2 + test %r8d,%r8d + jz .Lblocks + +.Lblocks_avx2: + and \$-16,$len + jz .Lno_data_avx2 + + vzeroupper + + test %r8d,%r8d + jz .Lbase2_64_avx2 + + test \$63,$len + jz .Leven_avx2 + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lblocks_avx2_body: + + mov $len,%r15 # reassign $len + + mov 0($ctx),$d1 # load hash value + mov 8($ctx),$d2 + mov 16($ctx),$h2#d + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + ################################# base 2^26 -> base 2^64 + mov $d1#d,$h0#d + and \$-1<<31,$d1 + mov $d2,$r1 # borrow $r1 + mov $d2#d,$h1#d + and \$-1<<31,$d2 + + shr \$6,$d1 + shl \$52,$r1 + add $d1,$h0 + shr \$12,$h1 + shr \$18,$d2 + add $r1,$h0 + adc $d2,$h1 + + mov $h2,$d1 + shl \$40,$d1 + shr \$24,$h2 + add $d1,$h1 + adc \$0,$h2 # can be partially reduced... + + mov \$-4,$d2 # ... so reduce + mov $h2,$d1 + and $h2,$d2 + shr \$2,$d1 + and \$3,$h2 + add $d2,$d1 # =*5 + add $d1,$h0 + adc \$0,$h1 + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + +.Lbase2_26_pre_avx2: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + mov $r1,%rax + + test \$63,%r15 + jnz .Lbase2_26_pre_avx2 + + test $padbit,$padbit # if $padbit is zero, + jz .Lstore_base2_64_avx2 # store hash in base 2^64 format + + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$r0 + mov $h1,$r1 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$r0 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $r0,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$r1 + and \$0x3ffffff,$h1 # h[3] + or $r1,$h2 # h[4] + + test %r15,%r15 + jz .Lstore_base2_26_avx2 + + vmovd %rax#d,%x#$H0 + vmovd %rdx#d,%x#$H1 + vmovd $h0#d,%x#$H2 + vmovd $h1#d,%x#$H3 + vmovd $h2#d,%x#$H4 + jmp .Lproceed_avx2 + +.align 32 +.Lstore_base2_64_avx2: + mov $h0,0($ctx) + mov $h1,8($ctx) + mov $h2,16($ctx) # note that is_base2_26 is zeroed + jmp .Ldone_avx2 + +.align 16 +.Lstore_base2_26_avx2: + mov %rax#d,0($ctx) # store hash value base 2^26 + mov %rdx#d,4($ctx) + mov $h0#d,8($ctx) + mov $h1#d,12($ctx) + mov $h2#d,16($ctx) +.align 16 +.Ldone_avx2: + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rsp +.Lno_data_avx2: +.Lblocks_avx2_epilogue: + ret + +.align 32 +.Lbase2_64_avx2: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lbase2_64_avx2_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2#d + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + test \$63,$len + jz .Linit_avx2 + +.Lbase2_64_pre_avx2: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + mov $r1,%rax + + test \$63,%r15 + jnz .Lbase2_64_pre_avx2 + +.Linit_avx2: + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$d1 + mov $h1,$d2 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$d1 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $d1,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$d2 + and \$0x3ffffff,$h1 # h[3] + or $d2,$h2 # h[4] + + vmovd %rax#d,%x#$H0 + vmovd %rdx#d,%x#$H1 + vmovd $h0#d,%x#$H2 + vmovd $h1#d,%x#$H3 + vmovd $h2#d,%x#$H4 + movl \$1,20($ctx) # set is_base2_26 + + call __poly1305_init_avx + +.Lproceed_avx2: + mov %r15,$len + + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rax + lea 48(%rsp),%rsp +.Lbase2_64_avx2_epilogue: + jmp .Ldo_avx2 + +.align 32 +.Leven_avx2: + vmovd 4*0($ctx),%x#$H0 # load hash value base 2^26 + vmovd 4*1($ctx),%x#$H1 + vmovd 4*2($ctx),%x#$H2 + vmovd 4*3($ctx),%x#$H3 + vmovd 4*4($ctx),%x#$H4 + +.Ldo_avx2: +___ +$code.=<<___ if (!$win64); + lea -8(%rsp),%r11 + sub \$0x128,%rsp +___ +$code.=<<___ if ($win64); + lea -0xf8(%rsp),%r11 + sub \$0x1c8,%rsp + vmovdqa %xmm6,0x50(%r11) + vmovdqa %xmm7,0x60(%r11) + vmovdqa %xmm8,0x70(%r11) + vmovdqa %xmm9,0x80(%r11) + vmovdqa %xmm10,0x90(%r11) + vmovdqa %xmm11,0xa0(%r11) + vmovdqa %xmm12,0xb0(%r11) + vmovdqa %xmm13,0xc0(%r11) + vmovdqa %xmm14,0xd0(%r11) + vmovdqa %xmm15,0xe0(%r11) +.Ldo_avx2_body: +___ +$code.=<<___; + lea 48+64($ctx),$ctx # size optimization + lea .Lconst(%rip),%rcx + + # expand and copy pre-calculated table to stack + vmovdqu `16*0-64`($ctx),%x#$T2 + and \$-512,%rsp + vmovdqu `16*1-64`($ctx),%x#$T3 + vmovdqu `16*2-64`($ctx),%x#$T4 + vmovdqu `16*3-64`($ctx),%x#$D0 + vmovdqu `16*4-64`($ctx),%x#$D1 + vmovdqu `16*5-64`($ctx),%x#$D2 + vmovdqu `16*6-64`($ctx),%x#$D3 + vpermq \$0x15,$T2,$T2 # 00003412 -> 12343434 + vmovdqu `16*7-64`($ctx),%x#$D4 + vpermq \$0x15,$T3,$T3 + vpshufd \$0xc8,$T2,$T2 # 12343434 -> 14243444 + vmovdqu `16*8-64`($ctx),%x#$MASK + vpermq \$0x15,$T4,$T4 + vpshufd \$0xc8,$T3,$T3 + vmovdqa $T2,0x00(%rsp) + vpermq \$0x15,$D0,$D0 + vpshufd \$0xc8,$T4,$T4 + vmovdqa $T3,0x20(%rsp) + vpermq \$0x15,$D1,$D1 + vpshufd \$0xc8,$D0,$D0 + vmovdqa $T4,0x40(%rsp) + vpermq \$0x15,$D2,$D2 + vpshufd \$0xc8,$D1,$D1 + vmovdqa $D0,0x60(%rsp) + vpermq \$0x15,$D3,$D3 + vpshufd \$0xc8,$D2,$D2 + vmovdqa $D1,0x80(%rsp) + vpermq \$0x15,$D4,$D4 + vpshufd \$0xc8,$D3,$D3 + vmovdqa $D2,0xa0(%rsp) + vpermq \$0x15,$MASK,$MASK + vpshufd \$0xc8,$D4,$D4 + vmovdqa $D3,0xc0(%rsp) + vpshufd \$0xc8,$MASK,$MASK + vmovdqa $D4,0xe0(%rsp) + vmovdqa $MASK,0x100(%rsp) + vmovdqa 64(%rcx),$MASK # .Lmask26 + + ################################################################ + # load input + vmovdqu 16*0($inp),%x#$T0 + vmovdqu 16*1($inp),%x#$T1 + vinserti128 \$1,16*2($inp),$T0,$T0 + vinserti128 \$1,16*3($inp),$T1,$T1 + lea 16*4($inp),$inp + + vpsrldq \$6,$T0,$T2 # splat input + vpsrldq \$6,$T1,$T3 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpunpcklqdq $T3,$T2,$T2 # 2:3 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + + vpsrlq \$30,$T2,$T3 + vpsrlq \$4,$T2,$T2 + vpsrlq \$26,$T0,$T1 + vpsrlq \$40,$T4,$T4 # 4 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T0,$T0 # 0 + vpand $MASK,$T1,$T1 # 1 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + lea 0x90(%rsp),%rax # size optimization + vpaddq $H2,$T2,$H2 # accumulate input + sub \$64,$len + jz .Ltail_avx2 + jmp .Loop_avx2 + +.align 32 +.Loop_avx2: + ################################################################ + # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4 + # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3 + # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2 + # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1 + # \________/\________/ + ################################################################ + #vpaddq $H2,$T2,$H2 # accumulate input + vpaddq $H0,$T0,$H0 + vmovdqa `32*0`(%rsp),$T0 # r0^4 + vpaddq $H1,$T1,$H1 + vmovdqa `32*1`(%rsp),$T1 # r1^4 + vpaddq $H3,$T3,$H3 + vmovdqa `32*3`(%rsp),$T2 # r2^4 + vpaddq $H4,$T4,$H4 + vmovdqa `32*6-0x90`(%rax),$T3 # s3^4 + vmovdqa `32*8-0x90`(%rax),$S4 # s4^4 + + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + # + # however, as h2 is "chronologically" first one available pull + # corresponding operations up, so it's + # + # d4 = h2*r2 + h4*r0 + h3*r1 + h1*r3 + h0*r4 + # d3 = h2*r1 + h3*r0 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h2*5*r4 + h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + # d0 = h2*5*r3 + h0*r0 + h4*5*r1 + h3*5*r2 + h1*5*r4 + + vpmuludq $H2,$T0,$D2 # d2 = h2*r0 + vpmuludq $H2,$T1,$D3 # d3 = h2*r1 + vpmuludq $H2,$T2,$D4 # d4 = h2*r2 + vpmuludq $H2,$T3,$D0 # d0 = h2*s3 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + + vpmuludq $H0,$T1,$T4 # h0*r1 + vpmuludq $H1,$T1,$H2 # h1*r1, borrow $H2 as temp + vpaddq $T4,$D1,$D1 # d1 += h0*r1 + vpaddq $H2,$D2,$D2 # d2 += h1*r1 + vpmuludq $H3,$T1,$T4 # h3*r1 + vpmuludq `32*2`(%rsp),$H4,$H2 # h4*s1 + vpaddq $T4,$D4,$D4 # d4 += h3*r1 + vpaddq $H2,$D0,$D0 # d0 += h4*s1 + vmovdqa `32*4-0x90`(%rax),$T1 # s2 + + vpmuludq $H0,$T0,$T4 # h0*r0 + vpmuludq $H1,$T0,$H2 # h1*r0 + vpaddq $T4,$D0,$D0 # d0 += h0*r0 + vpaddq $H2,$D1,$D1 # d1 += h1*r0 + vpmuludq $H3,$T0,$T4 # h3*r0 + vpmuludq $H4,$T0,$H2 # h4*r0 + vmovdqu 16*0($inp),%x#$T0 # load input + vpaddq $T4,$D3,$D3 # d3 += h3*r0 + vpaddq $H2,$D4,$D4 # d4 += h4*r0 + vinserti128 \$1,16*2($inp),$T0,$T0 + + vpmuludq $H3,$T1,$T4 # h3*s2 + vpmuludq $H4,$T1,$H2 # h4*s2 + vmovdqu 16*1($inp),%x#$T1 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + vpaddq $H2,$D1,$D1 # d1 += h4*s2 + vmovdqa `32*5-0x90`(%rax),$H2 # r3 + vpmuludq $H1,$T2,$T4 # h1*r2 + vpmuludq $H0,$T2,$T2 # h0*r2 + vpaddq $T4,$D3,$D3 # d3 += h1*r2 + vpaddq $T2,$D2,$D2 # d2 += h0*r2 + vinserti128 \$1,16*3($inp),$T1,$T1 + lea 16*4($inp),$inp + + vpmuludq $H1,$H2,$T4 # h1*r3 + vpmuludq $H0,$H2,$H2 # h0*r3 + vpsrldq \$6,$T0,$T2 # splat input + vpaddq $T4,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $H3,$T3,$T4 # h3*s3 + vpmuludq $H4,$T3,$H2 # h4*s3 + vpsrldq \$6,$T1,$T3 + vpaddq $T4,$D1,$D1 # d1 += h3*s3 + vpaddq $H2,$D2,$D2 # d2 += h4*s3 + vpunpckhqdq $T1,$T0,$T4 # 4 + + vpmuludq $H3,$S4,$H3 # h3*s4 + vpmuludq $H4,$S4,$H4 # h4*s4 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + vpmuludq `32*7-0x90`(%rax),$H0,$H4 # h0*r4 + vpmuludq $H1,$S4,$H0 # h1*s4 + vmovdqa 64(%rcx),$MASK # .Lmask26 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + ################################################################ + # lazy reduction (interleaved with tail of input splat) + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D4 + vpand $MASK,$H4,$H4 + + vpsrlq \$4,$T3,$T2 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpand $MASK,$T2,$T2 # 2 + vpsrlq \$26,$T0,$T1 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpaddq $T2,$H2,$H2 # modulo-scheduled + vpsrlq \$30,$T3,$T3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$40,$T4,$T4 # 4 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpand $MASK,$T0,$T0 # 0 + vpand $MASK,$T1,$T1 # 1 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + sub \$64,$len + jnz .Loop_avx2 + + .byte 0x66,0x90 +.Ltail_avx2: + ################################################################ + # while above multiplications were by r^4 in all lanes, in last + # iteration we multiply least significant lane by r^4 and most + # significant one by r, so copy of above except that references + # to the precomputed table are displaced by 4... + + #vpaddq $H2,$T2,$H2 # accumulate input + vpaddq $H0,$T0,$H0 + vmovdqu `32*0+4`(%rsp),$T0 # r0^4 + vpaddq $H1,$T1,$H1 + vmovdqu `32*1+4`(%rsp),$T1 # r1^4 + vpaddq $H3,$T3,$H3 + vmovdqu `32*3+4`(%rsp),$T2 # r2^4 + vpaddq $H4,$T4,$H4 + vmovdqu `32*6+4-0x90`(%rax),$T3 # s3^4 + vmovdqu `32*8+4-0x90`(%rax),$S4 # s4^4 + + vpmuludq $H2,$T0,$D2 # d2 = h2*r0 + vpmuludq $H2,$T1,$D3 # d3 = h2*r1 + vpmuludq $H2,$T2,$D4 # d4 = h2*r2 + vpmuludq $H2,$T3,$D0 # d0 = h2*s3 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + + vpmuludq $H0,$T1,$T4 # h0*r1 + vpmuludq $H1,$T1,$H2 # h1*r1 + vpaddq $T4,$D1,$D1 # d1 += h0*r1 + vpaddq $H2,$D2,$D2 # d2 += h1*r1 + vpmuludq $H3,$T1,$T4 # h3*r1 + vpmuludq `32*2+4`(%rsp),$H4,$H2 # h4*s1 + vpaddq $T4,$D4,$D4 # d4 += h3*r1 + vpaddq $H2,$D0,$D0 # d0 += h4*s1 + + vpmuludq $H0,$T0,$T4 # h0*r0 + vpmuludq $H1,$T0,$H2 # h1*r0 + vpaddq $T4,$D0,$D0 # d0 += h0*r0 + vmovdqu `32*4+4-0x90`(%rax),$T1 # s2 + vpaddq $H2,$D1,$D1 # d1 += h1*r0 + vpmuludq $H3,$T0,$T4 # h3*r0 + vpmuludq $H4,$T0,$H2 # h4*r0 + vpaddq $T4,$D3,$D3 # d3 += h3*r0 + vpaddq $H2,$D4,$D4 # d4 += h4*r0 + + vpmuludq $H3,$T1,$T4 # h3*s2 + vpmuludq $H4,$T1,$H2 # h4*s2 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + vpaddq $H2,$D1,$D1 # d1 += h4*s2 + vmovdqu `32*5+4-0x90`(%rax),$H2 # r3 + vpmuludq $H1,$T2,$T4 # h1*r2 + vpmuludq $H0,$T2,$T2 # h0*r2 + vpaddq $T4,$D3,$D3 # d3 += h1*r2 + vpaddq $T2,$D2,$D2 # d2 += h0*r2 + + vpmuludq $H1,$H2,$T4 # h1*r3 + vpmuludq $H0,$H2,$H2 # h0*r3 + vpaddq $T4,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $H3,$T3,$T4 # h3*s3 + vpmuludq $H4,$T3,$H2 # h4*s3 + vpaddq $T4,$D1,$D1 # d1 += h3*s3 + vpaddq $H2,$D2,$D2 # d2 += h4*s3 + + vpmuludq $H3,$S4,$H3 # h3*s4 + vpmuludq $H4,$S4,$H4 # h4*s4 + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4 + vpmuludq `32*7+4-0x90`(%rax),$H0,$H4 # h0*r4 + vpmuludq $H1,$S4,$H0 # h1*s4 + vmovdqa 64(%rcx),$MASK # .Lmask26 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + ################################################################ + # horizontal addition + + vpsrldq \$8,$D1,$T1 + vpsrldq \$8,$H2,$T2 + vpsrldq \$8,$H3,$T3 + vpsrldq \$8,$H4,$T4 + vpsrldq \$8,$H0,$T0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$H2,$H2 + vpaddq $T3,$H3,$H3 + vpaddq $T4,$H4,$H4 + vpaddq $T0,$H0,$H0 + + vpermq \$0x2,$H3,$T3 + vpermq \$0x2,$H4,$T4 + vpermq \$0x2,$H0,$T0 + vpermq \$0x2,$D1,$T1 + vpermq \$0x2,$H2,$T2 + vpaddq $T3,$H3,$H3 + vpaddq $T4,$H4,$H4 + vpaddq $T0,$H0,$H0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$H2,$H2 + + ################################################################ + # lazy reduction + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D4 + vpand $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vmovd %x#$H0,`4*0-48-64`($ctx)# save partially reduced + vmovd %x#$H1,`4*1-48-64`($ctx) + vmovd %x#$H2,`4*2-48-64`($ctx) + vmovd %x#$H3,`4*3-48-64`($ctx) + vmovd %x#$H4,`4*4-48-64`($ctx) +___ +$code.=<<___ if ($win64); + vmovdqa 0x50(%r11),%xmm6 + vmovdqa 0x60(%r11),%xmm7 + vmovdqa 0x70(%r11),%xmm8 + vmovdqa 0x80(%r11),%xmm9 + vmovdqa 0x90(%r11),%xmm10 + vmovdqa 0xa0(%r11),%xmm11 + vmovdqa 0xb0(%r11),%xmm12 + vmovdqa 0xc0(%r11),%xmm13 + vmovdqa 0xd0(%r11),%xmm14 + vmovdqa 0xe0(%r11),%xmm15 + lea 0xf8(%r11),%rsp +.Ldo_avx2_epilogue: +___ +$code.=<<___ if (!$win64); + lea 8(%r11),%rsp +___ +$code.=<<___; + vzeroupper + ret +.size poly1305_blocks_avx2,.-poly1305_blocks_avx2 +___ +} +$code.=<<___; +.align 64 +.Lconst: +.Lmask24: +.long 0x0ffffff,0,0x0ffffff,0,0x0ffffff,0,0x0ffffff,0 +.L129: +.long 1<<24,0,1<<24,0,1<<24,0,1<<24,0 +.Lmask26: +.long 0x3ffffff,0,0x3ffffff,0,0x3ffffff,0,0x3ffffff,0 +.Lfive: +.long 5,0,5,0,5,0,5,0 +___ +} + +$code.=<<___; +.asciz "Poly1305 for x86_64, CRYPTOGAMS by " +.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 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<.Lprologue + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + lea 48(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R14 + + jmp .Lcommon_seh_tail +.size se_handler,.-se_handler + +.type avx_handler,\@abi-omnipotent +.align 16 +avx_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->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 208($context),%rax # pull context->R11 + + lea 0x50(%rax),%rsi + lea 0xf8(%rax),%rax + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .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 avx_handler,.-avx_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_poly1305_init + .rva .LSEH_end_poly1305_init + .rva .LSEH_info_poly1305_init + + .rva .LSEH_begin_poly1305_blocks + .rva .LSEH_end_poly1305_blocks + .rva .LSEH_info_poly1305_blocks + + .rva .LSEH_begin_poly1305_emit + .rva .LSEH_end_poly1305_emit + .rva .LSEH_info_poly1305_emit +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_poly1305_blocks_avx + .rva .Lbase2_64_avx + .rva .LSEH_info_poly1305_blocks_avx_1 + + .rva .Lbase2_64_avx + .rva .Leven_avx + .rva .LSEH_info_poly1305_blocks_avx_2 + + .rva .Leven_avx + .rva .LSEH_end_poly1305_blocks_avx + .rva .LSEH_info_poly1305_blocks_avx_3 + + .rva .LSEH_begin_poly1305_emit_avx + .rva .LSEH_end_poly1305_emit_avx + .rva .LSEH_info_poly1305_emit_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_poly1305_blocks_avx2 + .rva .Lbase2_64_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_1 + + .rva .Lbase2_64_avx2 + .rva .Leven_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_2 + + .rva .Leven_avx2 + .rva .LSEH_end_poly1305_blocks_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_3 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_poly1305_init: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_init,.LSEH_begin_poly1305_init + +.LSEH_info_poly1305_blocks: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_body,.Lblocks_epilogue + +.LSEH_info_poly1305_emit: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_emit,.LSEH_begin_poly1305_emit +___ +$code.=<<___ if ($avx); +.LSEH_info_poly1305_blocks_avx_1: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_avx_body,.Lblocks_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx_2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbase2_64_avx_body,.Lbase2_64_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx_3: + .byte 9,0,0,0 + .rva avx_handler + .rva .Ldo_avx_body,.Ldo_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_emit_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_emit_avx,.LSEH_begin_poly1305_emit_avx +___ +$code.=<<___ if ($avx>1); +.LSEH_info_poly1305_blocks_avx2_1: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_avx2_body,.Lblocks_avx2_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx2_2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbase2_64_avx2_body,.Lbase2_64_avx2_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx2_3: + .byte 9,0,0,0 + .rva avx_handler + .rva .Ldo_avx2_body,.Ldo_avx2_epilogue # HandlerData[] +___ +} + +foreach (split('\n',$code)) { + s/\`([^\`]*)\`/eval($1)/ge; + s/%r([a-z]+)#d/%e$1/g; + s/%r([0-9]+)#d/%r$1d/g; + s/%x#%y/%x/g; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/poly1305/internal.h b/external/boringssl/crypto/poly1305/internal.h new file mode 100644 index 0000000000..df6769ea4c --- /dev/null +++ b/external/boringssl/crypto/poly1305/internal.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2016, 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_INTERNAL_H +#define OPENSSL_HEADER_POLY1305_INTERNAL_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#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 + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_POLY1305_INTERNAL_H */ diff --git a/external/boringssl/crypto/poly1305/poly1305.c b/external/boringssl/crypto/poly1305/poly1305.c new file mode 100644 index 0000000000..dc2d6a68a9 --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305.c @@ -0,0 +1,324 @@ +/* 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 + +#include + +#include + +#include "internal.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 + +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_capable()) { + 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_capable()) { + 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_capable()) { + 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/external/boringssl/crypto/poly1305/poly1305_arm.c b/external/boringssl/crypto/poly1305/poly1305_arm.c new file mode 100644 index 0000000000..de31d6b277 --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305_arm.c @@ -0,0 +1,304 @@ +/* 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 + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) + +#include + +#include "../internal.h" +#include "internal.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) { + unsigned 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 alignas(16) fe1305x2 zero; + +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/external/boringssl/crypto/poly1305/poly1305_arm_asm.S b/external/boringssl/crypto/poly1305/poly1305_arm_asm.S new file mode 100644 index 0000000000..e16f83bdd0 --- /dev/null +++ b/external/boringssl/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 +bic sp,sp,#31 + +# qhasm: len = input_3 +# asm 1: mov >len=int32#4,len=r3,y12=reg128#2%bot->y12=reg128#2%top},[y12=d2->y12=d3},[y34=reg128#3%bot->y34=reg128#3%top},[y34=d4->y34=d5},[input_1=int32#2,input_1=r1,z12=reg128#5%bot->z12=reg128#5%top},[z12=d8->z12=d9},[z34=reg128#6%bot->z34=reg128#6%top},[z34=d10->z34=d11},[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},[x01=d16->x01=d17},[x23=reg128#10%bot->x23=reg128#10%top},[x23=d18->x23=d19},[input_0=int32#1,input_0=r0,>=6 +# asm 1: vshr.u64 >mask=reg128#7,mask=q6,>= 7 +# asm 1: vshr.u64 >u4=reg128#8,u4=q7,5y12=reg128#12,5y12=q11,5y34=reg128#13,5y34=q12,5y12=reg128#12,<5y12=reg128#12,5y12=q11,<5y12=q11,5y34=reg128#13,<5y34=reg128#13,5y34=q12,<5y34=q12,u4=reg128#8,u4=q7,5z12=reg128#14,5z12=q13,5z34=reg128#15,5z34=q14,5z12=reg128#14,<5z12=reg128#14,5z12=q13,<5z12=q13,5z34=reg128#15,<5z34=reg128#15,5z34=q14,<5z34=q14,ptr=int32#2,ptr=r1,r4=reg128#16,r4=q15,r0=reg128#8,r0=q7,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,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,<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,<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,<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},[? len - 64 +# asm 1: cmp +bls ._below64bytes + +# qhasm: input_2 += 32 +# asm 1: add >input_2=int32#2,input_2=r1,c01=reg128#1%bot->c01=reg128#1%top},[c01=d0->c01=d1},[c23=reg128#2%bot->c23=reg128#2%top},[c23=d2->c23=d3},[ptr=int32#3,ptr=r2,z12=reg128#3%bot->z12=reg128#3%top},[z12=d4->z12=d5},[ptr=int32#3,ptr=r2,z0=reg128#4%bot->z0=reg128#4%top},[z0=d6->z0=d7},[r3=reg128#5,r3=q4,input_2=int32#2,input_2=r1,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},[5z34=d10->5z34=d11},[r0=reg128#8,r0=q7,r2=reg128#14,r2=q13,d01=reg128#12%bot->d01=reg128#12%top},[d01=d22->d01=d23},[r1=reg128#15,r1=q14,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},[5z12=d0->5z12=d1},[d23=reg128#2%bot->d23=reg128#2%top},[d23=d2->d23=d3},[input_2=int32#2,input_2=r1,> 40 +# asm 1: vshr.u64 >v4=reg128#4,v4=q3,> 14; v23[3] = d23[2,3] unsigned>> 14 +# asm 1: vshrn.u64 > 26; v01[3] = d01[2,3] unsigned>> 26 +# asm 1: vshrn.u64 > 20; v23[1] = mid[2,3] unsigned>> 20 +# asm 1: vshrn.u64 ptr=int32#3,ptr=r2,y34=reg128#3%bot->y34=reg128#3%top},[y34=d4->y34=d5},[ptr=int32#3,ptr=r2,y12=reg128#2%bot->y12=reg128#2%top},[y12=d2->y12=d3},[ptr=int32#3,ptr=r2,y0=reg128#1%bot->y0=reg128#1%top},[y0=d0->y0=d1},[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},[5y34=d24->5y34=d25},[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},[5y12=d22->5y12=d23},[ptr=int32#3,ptr=r2,> 26 +# asm 1: vshr.u64 >t1=reg128#4,t1=q3,len=int32#4,len=r3,r0=reg128#6,r0=q5,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t4=reg128#8,t4=q7,r3=reg128#5,r3=q4,x4=reg128#8,x4=q7,r4=reg128#16%bot->r4=reg128#16%top},[r4=d30->r4=d31},[> 26 +# asm 1: vshr.u64 >t2=reg128#9,t2=q8,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t0=reg128#10,t0=q9,r2=reg128#9,r2=q8,x4=reg128#11,x4=q10,x01=reg128#6,x01=q5,r0=reg128#8%bot->r0=reg128#8%top},[r0=d14->r0=d15},[ptr=int32#3,ptr=r2,t0=reg128#10,t0=q9,> 26 +# asm 1: vshr.u64 >t3=reg128#14,t3=q13,x01=reg128#15,x01=q14,z34=reg128#6%bot->z34=reg128#6%top},[z34=d10->z34=d11},[x23=reg128#10,x23=q9,r3=reg128#5,r3=q4,input_2=int32#2,input_2=r1,> 26 +# asm 1: vshr.u64 >t1=reg128#14,t1=q13,x01=reg128#9,x01=q8,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t4=reg128#14,t4=q13,r3=reg128#5,r3=q4,x4=reg128#11,x4=q10,? len - 64 +# asm 1: cmp +bhi ._mainloop2 + +# qhasm: input_2 -= 32 +# asm 1: sub >input_2=int32#3,input_2=r2,? len - 32 +# asm 1: cmp +bls ._end + +# qhasm: mainloop: +._mainloop: + +# qhasm: new r0 + +# qhasm: ptr = &two24 +# asm 1: lea >ptr=int32#2,ptr=r1,r4=reg128#5%bot->r4=reg128#5%top},[r4=d8->r4=d9},[u4=reg128#6%bot->u4=reg128#6%top},[u4=d10->u4=d11},[c01=reg128#8%bot->c01=reg128#8%top},[c01=d14->c01=d15},[c23=reg128#14%bot->c23=reg128#14%top},[c23=d26->c23=d27},[r0=reg128#4,r0=q3,r3=reg128#6,r3=q5,r1=reg128#14,r1=q13,r2=reg128#8,r2=q7,> 26 +# asm 1: vshr.u64 >t1=reg128#9,t1=q8,r0=reg128#4,r0=q3,r1=reg128#9,r1=q8,> 26 +# asm 1: vshr.u64 >t4=reg128#10,t4=q9,r3=reg128#6,r3=q5,r4=reg128#5,r4=q4,> 26 +# asm 1: vshr.u64 >t2=reg128#10,t2=q9,r1=reg128#11,r1=q10,> 26 +# asm 1: vshr.u64 >t0=reg128#9,t0=q8,r2=reg128#8,r2=q7,r4=reg128#5,r4=q4,r0=reg128#4,r0=q3,t0=reg128#9,t0=q8,> 26 +# asm 1: vshr.u64 >t3=reg128#14,t3=q13,r0=reg128#4,r0=q3,x23=reg128#10,x23=q9,r3=reg128#6,r3=q5,> 26 +# asm 1: vshr.u64 >t1=reg128#8,t1=q7,x01=reg128#9,x01=q8,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t4=reg128#8,t4=q7,r3=reg128#6,r3=q5,x4=reg128#11,x4=q10,len=int32#4,len=r3,? len - 32 +# asm 1: cmp +bhi ._mainloop + +# qhasm: end: +._end: + +# qhasm: mem128[input_0] = x01;input_0+=16 +# asm 1: vst1.8 {len=int32#1,len=r0,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},[y01=d2->y01=d3},[_5y01=reg128#3,_5y01=q2,y23=reg128#4%bot->y23=reg128#4%top},[y23=d6->y23=d7},[_5y23=reg128#9,_5y23=q8,_5y4=reg128#11,_5y4=q10,x01=reg128#12%bot->x01=reg128#12%top},[x01=d22->x01=d23},[_5y01=reg128#3,<_5y01=reg128#3,_5y01=q2,<_5y01=q2,x23=reg128#13%bot->x23=reg128#13%top},[x23=d24->x23=d25},[_5y23=reg128#9,<_5y23=reg128#9,_5y23=q8,<_5y23=q8,_5y4=reg128#11,<_5y4=reg128#11,_5y4=q10,<_5y4=q10,c01=reg128#14%bot->c01=reg128#14%top},[c01=d26->c01=d27},[x01=reg128#12,x01=q11,c23=reg128#14%bot->c23=reg128#14%top},[c23=d26->c23=d27},[x23=reg128#13,x23=q12,>=6 +# asm 1: vshr.u64 >mask=reg128#1,mask=q0,x4=reg128#14,x4=q13,r0=reg128#15,r0=q14,r1=reg128#3,r1=q2,r2=reg128#16,r2=q15,r3=reg128#9,r3=q8,r4=reg128#10,r4=q9,> 26 +# asm 1: vshr.u64 >t1=reg128#2,t1=q1,r0=reg128#4,r0=q3,r1=reg128#2,r1=q1,> 26 +# asm 1: vshr.u64 >t4=reg128#3,t4=q2,r3=reg128#9,r3=q8,r4=reg128#3,r4=q2,> 26 +# asm 1: vshr.u64 >t2=reg128#10,t2=q9,r1=reg128#2,r1=q1,> 26 +# asm 1: vshr.u64 >t0=reg128#11,t0=q10,r2=reg128#10,r2=q9,r4=reg128#3,r4=q2,r0=reg128#4,r0=q3,t0=reg128#11,t0=q10,> 26 +# asm 1: vshr.u64 >t3=reg128#12,t3=q11,r0=reg128#4,r0=q3,x23=reg128#10,x23=q9,r3=reg128#9,r3=q8,> 26 +# asm 1: vshr.u64 >t1=reg128#11,t1=q10,x01=reg128#4,x01=q3,r1=reg128#2,r1=q1,> 26 +# asm 1: vshr.u64 >t4=reg128#11,t4=q10,r3=reg128#1,r3=q0,x4=reg128#3,x4=q2, +#include + +#include + +#include +#include + +#include "../internal.h" +#include "../test/file_test.h" + + +static bool TestSIMD(FileTest *t, unsigned excess, + const std::vector &key, + const std::vector &in, + const std::vector &mac) { + poly1305_state state; + CRYPTO_poly1305_init(&state, key.data()); + + size_t done = 0; + + // Feed 16 bytes in. Some implementations begin in non-SIMD mode and upgrade + // on-demand. Stress the upgrade path. + size_t todo = 16; + if (todo > in.size()) { + todo = in.size(); + } + CRYPTO_poly1305_update(&state, in.data(), todo); + done += todo; + + for (;;) { + // Feed 128 + |excess| bytes to test SIMD mode. + if (done + 128 + excess > in.size()) { + break; + } + CRYPTO_poly1305_update(&state, in.data() + done, 128 + excess); + done += 128 + excess; + + // Feed |excess| bytes to ensure SIMD mode can handle short inputs. + if (done + excess > in.size()) { + break; + } + CRYPTO_poly1305_update(&state, in.data() + done, excess); + done += excess; + } + + // Consume the remainder and finish. + CRYPTO_poly1305_update(&state, in.data() + done, in.size() - done); + + // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output. + alignas(16) uint8_t out[16]; + CRYPTO_poly1305_finish(&state, out); + if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) { + t->PrintLine("SIMD pattern %u failed.", excess); + return false; + } + + return true; +} + +static bool TestPoly1305(FileTest *t, void *arg) { + std::vector key, in, mac; + if (!t->GetBytes(&key, "Key") || + !t->GetBytes(&in, "Input") || + !t->GetBytes(&mac, "MAC")) { + return false; + } + if (key.size() != 32 || mac.size() != 16) { + t->PrintLine("Invalid test"); + return false; + } + + // Test single-shot operation. + poly1305_state state; + CRYPTO_poly1305_init(&state, key.data()); + CRYPTO_poly1305_update(&state, in.data(), in.size()); + // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output. + alignas(16) uint8_t out[16]; + CRYPTO_poly1305_finish(&state, out); + if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) { + t->PrintLine("Single-shot Poly1305 failed."); + return false; + } + + // Test streaming byte-by-byte. + CRYPTO_poly1305_init(&state, key.data()); + for (size_t i = 0; i < in.size(); i++) { + CRYPTO_poly1305_update(&state, &in[i], 1); + } + CRYPTO_poly1305_finish(&state, out); + if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) { + t->PrintLine("Streaming Poly1305 failed."); + return false; + } + + // Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of + // four blocks, so test up to three blocks of excess. + if (!TestSIMD(t, 0, key, in, mac) || + !TestSIMD(t, 16, key, in, mac) || + !TestSIMD(t, 32, key, in, mac) || + !TestSIMD(t, 48, key, in, mac)) { + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestPoly1305, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/poly1305/poly1305_tests.txt b/external/boringssl/crypto/poly1305/poly1305_tests.txt new file mode 100644 index 0000000000..611007a05f --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305_tests.txt @@ -0,0 +1,159 @@ +# RFC 7539, section 2.5.2. + +Key = 85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b +Input = "Cryptographic Forum Research Group" +MAC = a8061dc1305136c6c22b8baf0c0127a9 + + +# RFC 7539, section A.3. + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +MAC = 00000000000000000000000000000000 + +Key = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e +Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f +MAC = 36e5f6b5c5e06070f0efca96227a863e + +Key = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000 +Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f +MAC = f3477e7cd95417af89a6b8794c310cf0 + +Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0 +Input = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e +MAC = 4541669a7eaaee61e708dc7cbcc5eb62 + +Key = 0200000000000000000000000000000000000000000000000000000000000000 +Input = ffffffffffffffffffffffffffffffff +MAC = 03000000000000000000000000000000 + +Key = 02000000000000000000000000000000ffffffffffffffffffffffffffffffff +Input = 02000000000000000000000000000000 +MAC = 03000000000000000000000000000000 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Input = fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000 +MAC = 05000000000000000000000000000000 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Input = fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101 +MAC = 00000000000000000000000000000000 + +Key = 0200000000000000000000000000000000000000000000000000000000000000 +Input = fdffffffffffffffffffffffffffffff +MAC = faffffffffffffffffffffffffffffff + +Key = 0100000000000000040000000000000000000000000000000000000000000000 +Input = e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000 +MAC = 14000000000000005500000000000000 + +Key = 0100000000000000040000000000000000000000000000000000000000000000 +Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000 +MAC = 13000000000000000000000000000000 + + +# Additional test vectors that are long enough to ensure OpenSSL's SIMD +# assembly is fully tested. + +# Length 2048. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfed +MAC = 69d28f73dd09d39a92aa179da354b7ea + +# Length 2049. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc8 +MAC = d6a26654b88572e875d9661c83471c1b + +# Length 2050. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852 +MAC = 9fbbb7f7adcd0cd5b46a4a520b22499a + +# Length 2051. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f5 +MAC = eb7cdceb97ade2a07622f8f5a4b1ce15 + +# Length 2052. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f590 +MAC = d41c310927cd92e14784ea78b85503db + +# Length 2053. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073 +MAC = 16af133c423f783a14c49d9f526384cf + +# Length 2054. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4 +MAC = 00c75db8f0636b22f195645b03091f5f + +# Length 2055. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f434 +MAC = 4a532bc740f581555831345f3b75bf33 + +# Length 2056. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a +MAC = 698c7d32c5923871d124a2479e521706 + +# Length 2057. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c +MAC = a677187dbf3c927aeeafb9ebce0f61dc + +# Length 2058. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a +MAC = 201fed7eee981b31d2cc42ff6c38141a + +# Length 2059. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28 +MAC = 0c3d3d01a37f347c4f7c5826bcafb3e1 + +# Length 2060. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c9 +MAC = 33a4e0e0bed7c84c5cc5dd4784410f07 + +# Length 2061. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e +MAC = 8e41c40a2f8ec58fe594f3a3a2de4ae1 + +# Length 2062. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21 +MAC = c6e5d1810fd878ac6b844c66cef36a22 + +# Length 2063. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21df +MAC = f6eaae369c3cb5c05748e8d919178e00 + +# Regression test for https://rt.openssl.org/Ticket/Display.html?id=4439 +Key = 2d773be37adb1e4d683bf0075e79c4ee037918535a7f99ccb7040fb5f5f43aea +Input = 89dab80b7717c1db5db437860a3f70218e93e1b8f461fb677f16f35f6f87e2a91c99bc3a47ace47640cc95c345be5ecca5a3523c35cc01893af0b64a620334270372ec12482d1b1e363561698a578b359803495bb4e2ef1930b17a5190b580f141300df30adbeca28f6427a8bc1a999fd51c554a017d095d8c3e3127daf9f595 +MAC = c85d15ed44c378d6b00e23064c7bcd51 + +# Regression tests for https://rt.openssl.org/Ticket/Display.html?id=4483 + +Key = 7f1b02640000000000000000000000000000000000000000cccccccccccccccc +Input = cccccccccccccccccccccccccccccccccccccccccccccccccc80ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccceccccccccccccccccccccccccccccccccccccc5cccccccccccccccccccccccccccccccccccccccccce3ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaccccccccccccccccccccce6cccccccccc000000afccccccccccccccccccfffffff5000000000000000000000000000000000000000000000000000000ffffffe70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000719205a8521dfc +MAC = 8559b876eceed66eb37798c0457baff9 + +Key = e00016000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaa +Input = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000000000000000800264 +MAC = 00bd1258978e205444c9aaaa82006fed + +Key = 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c +Input = 02fc +MAC = 06120c0c0c0c0c0c0c0c0c0c0c0c0c0c + +Key = 00ff000000000000000000000000000000000000001e00000000000000007b7b +Input = 7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b007b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff0009000000000000000000000000100000000009000000640000000000000000000000001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff00090000000000000000007a000010000000000900000064000000000000000000000000000000000000000000000000fc +MAC = 33205bbf9e9f8f7212ab9e2ab9b7e4a5 diff --git a/external/boringssl/crypto/poly1305/poly1305_vec.c b/external/boringssl/crypto/poly1305/poly1305_vec.c new file mode 100644 index 0000000000..3045a2f1b7 --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305_vec.c @@ -0,0 +1,890 @@ +/* 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 + +#include "../internal.h" + + +#if !defined(OPENSSL_WINDOWS) && defined(OPENSSL_X86_64) + +#include + +#define U8TO64_LE(m) (*(const uint64_t *)(m)) +#define U8TO32_LE(m) (*(const uint32_t *)(m)) +#define U64TO8_LE(m, v) (*(uint64_t *)(m)) = v + +typedef __m128i xmmi; + +static const alignas(16) uint32_t poly1305_x64_sse2_message_mask[4] = { + (1 << 26) - 1, 0, (1 << 26) - 1, 0}; +static const alignas(16) uint32_t poly1305_x64_sse2_5[4] = {5, 0, 5, 0}; +static const alignas(16) uint32_t poly1305_x64_sse2_1shl128[4] = { + (1 << 24), 0, (1 << 24), 0}; + +static inline uint128_t add128(uint128_t a, uint128_t b) { return a + b; } + +static inline uint128_t add128_64(uint128_t a, uint64_t b) { return a + b; } + +static inline uint128_t mul64x64_128(uint64_t a, uint64_t b) { + return (uint128_t)a * b; +} + +static inline uint64_t lo128(uint128_t a) { return (uint64_t)a; } + +static inline uint64_t shr128(uint128_t v, const int shift) { + return (uint64_t)(v >> shift); +} + +static inline uint64_t 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 inline poly1305_state_internal *poly1305_aligned_state( + poly1305_state *state) { + return (poly1305_state_internal *)(((uint64_t)state + 63) & ~63); +} + +/* copy 0-63 bytes */ +static inline void +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((const xmmi *)(dst + offset + 0))); + _mm_storeu_si128((xmmi *)(dst + 16), + _mm_loadu_si128((const xmmi *)(dst + offset + 16))); + dst += 32; + } + if (bytes & 16) { + _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((const xmmi *)(dst + offset))); + dst += 16; + } + if (bytes & 8) { + *(uint64_t *)dst = *(const uint64_t *)(dst + offset); + dst += 8; + } + if (bytes & 4) { + *(uint32_t *)dst = *(const 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 inline void 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 inline size_t 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((const xmmi *)poly1305_x64_sse2_message_mask); + const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5); + const xmmi HIBIT = _mm_load_si128((const 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((const xmmi *)(m + 0)), + _mm_loadl_epi64((const xmmi *)(m + 16))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)), + _mm_loadl_epi64((const 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((const xmmi *)poly1305_x64_sse2_message_mask); + const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5); + const xmmi HIBIT = _mm_load_si128((const 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((const xmmi *)(m + 0)), + _mm_loadl_epi64((const xmmi *)(m + 16))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)), + _mm_loadl_epi64((const 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((const xmmi *)(m + 32)), + _mm_loadl_epi64((const xmmi *)(m + 48))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 40)), + _mm_loadl_epi64((const 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((const xmmi *)poly1305_x64_sse2_message_mask); + const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128); + const xmmi FIVE = _mm_load_si128((const 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((const xmmi *)(m + 0)), + _mm_loadl_epi64((const xmmi *)(m + 16))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)), + _mm_loadl_epi64((const 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)) & UINT64_C(0xfffffffffff); + st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & UINT64_C(0xfffffffffff); + st->HH[2] = ((t3 >> 10) | (t4 << 16)) & UINT64_C(0x3ffffffffff); + + 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/external/boringssl/crypto/rand/CMakeLists.txt b/external/boringssl/crypto/rand/CMakeLists.txt new file mode 100644 index 0000000000..c66d2eeb85 --- /dev/null +++ b/external/boringssl/crypto/rand/CMakeLists.txt @@ -0,0 +1,24 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + RAND_ARCH_SOURCES + + rdrand-x86_64.${ASM_EXT} + ) +endif() + +add_library( + rand + + OBJECT + + deterministic.c + rand.c + urandom.c + windows.c + + ${RAND_ARCH_SOURCES} +) + +perlasm(rdrand-x86_64.${ASM_EXT} asm/rdrand-x86_64.pl) diff --git a/external/boringssl/crypto/rand/asm/rdrand-x86_64.pl b/external/boringssl/crypto/rand/asm/rdrand-x86_64.pl new file mode 100644 index 0000000000..c32a55c4b9 --- /dev/null +++ b/external/boringssl/crypto/rand/asm/rdrand-x86_64.pl @@ -0,0 +1,75 @@ +#!/usr/bin/env perl + +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +print<<___; +.text + +# CRYPTO_rdrand writes eight bytes of random data from the hardware RNG to +# |out|. It returns one on success or zero on hardware failure. +# int CRYPTO_rdrand(uint8_t out[8]); +.globl CRYPTO_rdrand +.type CRYPTO_rdrand,\@function,1 +.align 16 +CRYPTO_rdrand: + xorq %rax, %rax + # This is rdrand %rcx. It sets rcx to a random value and sets the carry + # flag on success. + .byte 0x48, 0x0f, 0xc7, 0xf1 + # An add-with-carry of zero effectively sets %rax to the carry flag. + adcq %rax, %rax + movq %rcx, 0(%rdi) + retq + +# CRYPTO_rdrand_multiple8_buf fills |len| bytes at |buf| with random data from +# the hardware RNG. The |len| argument must be a multiple of eight. It returns +# one on success and zero on hardware failure. +# int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len); +.globl CRYPTO_rdrand_multiple8_buf +.type CRYPTO_rdrand_multiple8_buf,\@function,2 +.align 16 +CRYPTO_rdrand_multiple8_buf: + test %rsi, %rsi + jz .Lout + movq \$8, %rdx +.Lloop: + # This is rdrand %rcx. It sets rcx to a random value and sets the carry + # flag on success. + .byte 0x48, 0x0f, 0xc7, 0xf1 + jnc .Lerr + movq %rcx, 0(%rdi) + addq %rdx, %rdi + subq %rdx, %rsi + jnz .Lloop +.Lout: + movq \$1, %rax + retq +.Lerr: + xorq %rax, %rax + retq +___ + +close STDOUT; # flush diff --git a/external/boringssl/crypto/rand/deterministic.c b/external/boringssl/crypto/rand/deterministic.c new file mode 100644 index 0000000000..e6b7bb7eca --- /dev/null +++ b/external/boringssl/crypto/rand/deterministic.c @@ -0,0 +1,49 @@ +/* Copyright (c) 2016, 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 + +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +#include + +#include + +#include "internal.h" + + +/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occured. + * + * TODO(davidben): This is intentionally not thread-safe. If the fuzzer mode is + * ever used in a multi-threaded program, replace this with a thread-local. (A + * mutex would not be deterministic.) */ +static uint64_t g_num_calls = 0; + +void RAND_cleanup(void) {} + +void RAND_reset_for_fuzzing(void) { g_num_calls = 0; } + +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + static const uint8_t kZeroKey[32]; + + uint8_t nonce[12]; + memset(nonce, 0, sizeof(nonce)); + memcpy(nonce, &g_num_calls, sizeof(g_num_calls)); + + memset(out, 0, requested); + CRYPTO_chacha_20(out, out, requested, kZeroKey, nonce, 0); + g_num_calls++; +} + +#endif /* BORINGSSL_UNSAFE_FUZZER_MODE */ diff --git a/external/boringssl/crypto/rand/internal.h b/external/boringssl/crypto/rand/internal.h new file mode 100644 index 0000000000..dcff3aa6ee --- /dev/null +++ b/external/boringssl/crypto/rand/internal.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CRYPTO_sysrand fills |len| bytes at |buf| with entropy from the operating + * system. */ +void CRYPTO_sysrand(uint8_t *buf, size_t len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H */ diff --git a/external/boringssl/crypto/rand/rand.c b/external/boringssl/crypto/rand/rand.c new file mode 100644 index 0000000000..5a1bec2ef5 --- /dev/null +++ b/external/boringssl/crypto/rand/rand.c @@ -0,0 +1,242 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +/* It's assumed that the operating system always has an unfailing source of + * entropy which is accessed via |CRYPTO_sysrand|. (If the operating system + * entropy source fails, it's up to |CRYPTO_sysrand| to abort the process—we + * don't try to handle it.) + * + * In addition, the hardware may provide a low-latency RNG. Intel's rdrand + * instruction is the canonical example of this. When a hardware RNG is + * available we don't need to worry about an RNG failure arising from fork()ing + * the process or moving a VM, so we can keep thread-local RNG state and XOR + * the hardware entropy in. + * + * (We assume that the OS entropy is safe from fork()ing and VM duplication. + * This might be a bit of a leap of faith, esp on Windows, but there's nothing + * that we can do about it.) */ + +/* rand_thread_state contains the per-thread state for the RNG. This is only + * used if the system has support for a hardware RNG. */ +struct rand_thread_state { + uint8_t key[32]; + uint64_t calls_used; + size_t bytes_used; + uint8_t partial_block[64]; + unsigned partial_block_used; +}; + +/* kMaxCallsPerRefresh is the maximum number of |RAND_bytes| calls that we'll + * serve before reading a new key from the operating system. This only applies + * if we have a hardware RNG. */ +static const unsigned kMaxCallsPerRefresh = 1024; + +/* kMaxBytesPerRefresh is the maximum number of bytes that we'll return from + * |RAND_bytes| before reading a new key from the operating system. This only + * applies if we have a hardware RNG. */ +static const uint64_t kMaxBytesPerRefresh = 1024 * 1024; + +/* rand_thread_state_free frees a |rand_thread_state|. This is called when a + * thread exits. */ +static void rand_thread_state_free(void *state) { + if (state == NULL) { + return; + } + + OPENSSL_cleanse(state, sizeof(struct rand_thread_state)); + OPENSSL_free(state); +} + +#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \ + !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +/* These functions are defined in asm/rdrand-x86_64.pl */ +extern int CRYPTO_rdrand(uint8_t out[8]); +extern int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len); + +static int have_rdrand(void) { + return (OPENSSL_ia32cap_P[1] & (1u << 30)) != 0; +} + +static int hwrand(uint8_t *buf, size_t len) { + if (!have_rdrand()) { + return 0; + } + + const size_t len_multiple8 = len & ~7; + if (!CRYPTO_rdrand_multiple8_buf(buf, len_multiple8)) { + return 0; + } + len -= len_multiple8; + + if (len != 0) { + assert(len < 8); + + uint8_t rand_buf[8]; + if (!CRYPTO_rdrand(rand_buf)) { + return 0; + } + memcpy(buf + len_multiple8, rand_buf, len); + } + + return 1; +} + +#else + +static int hwrand(uint8_t *buf, size_t len) { + return 0; +} + +#endif + +int RAND_bytes(uint8_t *buf, size_t len) { + if (len == 0) { + return 1; + } + + if (!hwrand(buf, len)) { + /* Without a hardware RNG to save us from address-space duplication, the OS + * entropy is used directly. */ + CRYPTO_sysrand(buf, len); + return 1; + } + + struct rand_thread_state *state = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_RAND); + if (state == NULL) { + state = OPENSSL_malloc(sizeof(struct rand_thread_state)); + if (state == NULL || + !CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_RAND, state, + rand_thread_state_free)) { + CRYPTO_sysrand(buf, len); + return 1; + } + + memset(state->partial_block, 0, sizeof(state->partial_block)); + state->calls_used = kMaxCallsPerRefresh; + } + + if (state->calls_used >= kMaxCallsPerRefresh || + state->bytes_used >= kMaxBytesPerRefresh) { + CRYPTO_sysrand(state->key, sizeof(state->key)); + state->calls_used = 0; + state->bytes_used = 0; + state->partial_block_used = sizeof(state->partial_block); + } + + if (len >= sizeof(state->partial_block)) { + size_t remaining = len; + while (remaining > 0) { + /* kMaxBytesPerCall is only 2GB, while ChaCha can handle 256GB. But this + * is sufficient and easier on 32-bit. */ + static const size_t kMaxBytesPerCall = 0x80000000; + size_t todo = remaining; + if (todo > kMaxBytesPerCall) { + todo = kMaxBytesPerCall; + } + uint8_t nonce[12]; + memset(nonce, 0, 4); + memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used)); + CRYPTO_chacha_20(buf, buf, todo, state->key, nonce, 0); + buf += todo; + remaining -= todo; + state->calls_used++; + } + } else { + if (sizeof(state->partial_block) - state->partial_block_used < len) { + uint8_t nonce[12]; + memset(nonce, 0, 4); + memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used)); + CRYPTO_chacha_20(state->partial_block, state->partial_block, + sizeof(state->partial_block), state->key, nonce, 0); + state->partial_block_used = 0; + } + + unsigned i; + for (i = 0; i < len; i++) { + buf[i] ^= state->partial_block[state->partial_block_used++]; + } + state->calls_used++; + } + state->bytes_used += len; + + return 1; +} + +int RAND_pseudo_bytes(uint8_t *buf, size_t len) { + return RAND_bytes(buf, len); +} + +void RAND_seed(const void *buf, int num) { + /* OpenSSH calls |RAND_seed| before jailing on the assumption that any needed + * file descriptors etc will be opened. */ + uint8_t unused; + RAND_bytes(&unused, sizeof(unused)); +} + +int RAND_load_file(const char *path, long num) { + if (num < 0) { /* read the "whole file" */ + return 1; + } else if (num <= INT_MAX) { + return (int) num; + } else { + return INT_MAX; + } +} + +const char *RAND_file_name(char *buf, size_t num) { return NULL; } + +void RAND_add(const void *buf, int num, double entropy) {} + +int RAND_egd(const char *path) { + return 255; +} + +int RAND_poll(void) { + return 1; +} + +int RAND_status(void) { + return 1; +} + +static const struct rand_meth_st kSSLeayMethod = { + RAND_seed, + RAND_bytes, + RAND_cleanup, + RAND_add, + RAND_pseudo_bytes, + RAND_status, +}; + +RAND_METHOD *RAND_SSLeay(void) { + return (RAND_METHOD*) &kSSLeayMethod; +} + +void RAND_set_rand_method(const RAND_METHOD *method) {} diff --git a/external/boringssl/crypto/rand/urandom.c b/external/boringssl/crypto/rand/urandom.c new file mode 100644 index 0000000000..434fe4317c --- /dev/null +++ b/external/boringssl/crypto/rand/urandom.c @@ -0,0 +1,223 @@ +/* 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 + +#if !defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +#include +#include +#include +#include +#include + +#include +#include + +#include "internal.h" +#include "../internal.h" + + +/* This file implements a PRNG by reading from /dev/urandom, optionally with a + * buffer, which is unsafe across |fork|. */ + +#define BUF_SIZE 4096 + +/* rand_buffer contains unused, random bytes, some of which may have been + * consumed already. */ +struct rand_buffer { + size_t used; + uint8_t rand[BUF_SIZE]; +}; + +/* requested_lock is used to protect the |*_requested| variables. */ +static struct CRYPTO_STATIC_MUTEX requested_lock = CRYPTO_STATIC_MUTEX_INIT; + +/* urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by + * |requested_lock|. */ +static int urandom_fd_requested = -2; + +/* urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|. */ +static int urandom_fd = -2; + +/* urandom_buffering_requested is set by |RAND_enable_fork_unsafe_buffering|. + * It's protected by |requested_lock|. */ +static int urandom_buffering_requested = 0; + +/* urandom_buffering controls whether buffering is enabled (1) or not (0). This + * is protected by |once|. */ +static int urandom_buffering = 0; + +static CRYPTO_once_t once = CRYPTO_ONCE_INIT; + +/* init_once initializes the state of this module to values previously + * requested. This is the only function that modifies |urandom_fd| and + * |urandom_buffering|, whose values may be read safely after calling the + * once. */ +static void init_once(void) { + CRYPTO_STATIC_MUTEX_lock_read(&requested_lock); + urandom_buffering = urandom_buffering_requested; + int fd = urandom_fd_requested; + CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock); + + if (fd == -2) { + do { + fd = open("/dev/urandom", O_RDONLY); + } while (fd == -1 && errno == EINTR); + } + + if (fd < 0) { + abort(); + } + + int flags = fcntl(fd, F_GETFD); + if (flags == -1) { + /* Native Client doesn't implement |fcntl|. */ + if (errno != ENOSYS) { + abort(); + } + } else { + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) == -1) { + abort(); + } + } + urandom_fd = fd; +} + +void RAND_cleanup(void) {} + +void RAND_set_urandom_fd(int fd) { + fd = dup(fd); + if (fd < 0) { + abort(); + } + + CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); + urandom_fd_requested = fd; + CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); + + CRYPTO_once(&once, init_once); + if (urandom_fd != fd) { + abort(); // Already initialized. + } +} + +void RAND_enable_fork_unsafe_buffering(int fd) { + if (fd >= 0) { + fd = dup(fd); + if (fd < 0) { + abort(); + } + } else { + fd = -2; + } + + CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); + urandom_buffering_requested = 1; + urandom_fd_requested = fd; + CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); + + CRYPTO_once(&once, init_once); + if (urandom_buffering != 1 || (fd >= 0 && urandom_fd != fd)) { + abort(); // Already initialized. + } +} + +static struct rand_buffer *get_thread_local_buffer(void) { + struct rand_buffer *buf = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_URANDOM_BUF); + if (buf != NULL) { + return buf; + } + + buf = OPENSSL_malloc(sizeof(struct rand_buffer)); + if (buf == NULL) { + return NULL; + } + buf->used = BUF_SIZE; /* To trigger a |read_full| on first use. */ + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_URANDOM_BUF, buf, + OPENSSL_free)) { + OPENSSL_free(buf); + return NULL; + } + + return buf; +} + +/* 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; +} + +/* read_from_buffer reads |requested| random bytes from the buffer into |out|, + * refilling it if necessary to satisfy the request. */ +static void read_from_buffer(struct rand_buffer *buf, + uint8_t *out, size_t requested) { + size_t remaining = BUF_SIZE - buf->used; + + while (requested > remaining) { + memcpy(out, &buf->rand[buf->used], remaining); + buf->used += remaining; + out += remaining; + requested -= remaining; + + if (!read_full(urandom_fd, buf->rand, BUF_SIZE)) { + abort(); + return; + } + buf->used = 0; + remaining = BUF_SIZE; + } + + memcpy(out, &buf->rand[buf->used], requested); + buf->used += requested; +} + +/* CRYPTO_sysrand puts |requested| random bytes into |out|. */ +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + if (requested == 0) { + return; + } + + CRYPTO_once(&once, init_once); + if (urandom_buffering && requested < BUF_SIZE) { + struct rand_buffer *buf = get_thread_local_buffer(); + if (buf != NULL) { + read_from_buffer(buf, out, requested); + return; + } + } + + if (!read_full(urandom_fd, out, requested)) { + abort(); + } +} + +#endif /* !OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */ diff --git a/external/boringssl/crypto/rand/windows.c b/external/boringssl/crypto/rand/windows.c new file mode 100644 index 0000000000..5a9a96b417 --- /dev/null +++ b/external/boringssl/crypto/rand/windows.c @@ -0,0 +1,56 @@ +/* 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 + +#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(push, 3)) + +#include + +/* #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 +#undef SystemFunction036 + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#include "internal.h" + + +void RAND_cleanup(void) { +} + +void CRYPTO_sysrand(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; +} + +#endif /* OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */ diff --git a/external/boringssl/crypto/rc4/CMakeLists.txt b/external/boringssl/crypto/rc4/CMakeLists.txt new file mode 100644 index 0000000000..151773a799 --- /dev/null +++ b/external/boringssl/crypto/rc4/CMakeLists.txt @@ -0,0 +1,29 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + RC4_ARCH_SOURCES + + rc4-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-586.${ASM_EXT} asm/rc4-586.pl) diff --git a/external/boringssl/crypto/rc4/asm/rc4-586.pl b/external/boringssl/crypto/rc4/asm/rc4-586.pl new file mode 100644 index 0000000000..8d3ccb72ab --- /dev/null +++ b/external/boringssl/crypto/rc4/asm/rc4-586.pl @@ -0,0 +1,388 @@ +#!/usr/bin/env perl + +# ==================================================================== +# [Re]written by Andy Polyakov 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]. +# +# + +# 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"); + +&asm_finish(); + diff --git a/external/boringssl/crypto/rc4/asm/rc4-x86_64.pl b/external/boringssl/crypto/rc4/asm/rc4-x86_64.pl new file mode 100644 index 0000000000..cef6268914 --- /dev/null +++ b/external/boringssl/crypto/rc4/asm/rc4-x86_64.pl @@ -0,0 +1,653 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 +___ + +# 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->RipRsp + + 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/external/boringssl/crypto/rc4/rc4.c b/external/boringssl/crypto/rc4/rc4.c new file mode 100644 index 0000000000..b8e1d9f0da --- /dev/null +++ b/external/boringssl/crypto/rc4/rc4.c @@ -0,0 +1,283 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#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 + + +/* RC4 as implemented from a posting from + * Newsgroups: sci.crypt + * From: sterndark@netcom.com (David Sterndark) + * Subject: RC4 Algorithm revealed. + * Message-ID: + * Date: Wed, 14 Sep 1994 06:35:31 GMT */ + +void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) { + uint32_t *d; + uint32_t x, y, tx, ty; + size_t i; + + x = key->x; + y = key->y; + d = key->data; + +#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 + * 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 + * + * */ + 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); + } + } 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); + } + } + } +#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) { + uint32_t tmp; + unsigned i, id1, id2; + uint32_t *d; + + 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/external/boringssl/crypto/refcount_c11.c b/external/boringssl/crypto/refcount_c11.c new file mode 100644 index 0000000000..fbc0343d67 --- /dev/null +++ b/external/boringssl/crypto/refcount_c11.c @@ -0,0 +1,67 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + + +#if defined(OPENSSL_C11_ATOMIC) + +#include +#include +#include +#include + +#include + + +/* See comment above the typedef of CRYPTO_refcount_t about these tests. */ +static_assert(alignof(CRYPTO_refcount_t) == alignof(_Atomic CRYPTO_refcount_t), + "_Atomic alters the needed alignment of a reference count"); +static_assert(sizeof(CRYPTO_refcount_t) == sizeof(_Atomic CRYPTO_refcount_t), + "_Atomic alters the size of a reference count"); + +static_assert((CRYPTO_refcount_t)-1 == CRYPTO_REFCOUNT_MAX, + "CRYPTO_REFCOUNT_MAX is incorrect"); + +void CRYPTO_refcount_inc(CRYPTO_refcount_t *in_count) { + _Atomic CRYPTO_refcount_t *count = (_Atomic CRYPTO_refcount_t *) in_count; + uint32_t expected = atomic_load(count); + + while (expected != CRYPTO_REFCOUNT_MAX) { + uint32_t new_value = expected + 1; + if (atomic_compare_exchange_weak(count, &expected, new_value)) { + break; + } + } +} + +int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *in_count) { + _Atomic CRYPTO_refcount_t *count = (_Atomic CRYPTO_refcount_t *)in_count; + uint32_t expected = atomic_load(count); + + for (;;) { + if (expected == 0) { + abort(); + } else if (expected == CRYPTO_REFCOUNT_MAX) { + return 0; + } else { + const uint32_t new_value = expected - 1; + if (atomic_compare_exchange_weak(count, &expected, new_value)) { + return new_value == 0; + } + } + } +} + +#endif /* OPENSSL_C11_ATOMIC */ diff --git a/external/boringssl/crypto/refcount_lock.c b/external/boringssl/crypto/refcount_lock.c new file mode 100644 index 0000000000..ea6a06d39f --- /dev/null +++ b/external/boringssl/crypto/refcount_lock.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#include + +#include + + +#if !defined(OPENSSL_C11_ATOMIC) + +OPENSSL_COMPILE_ASSERT((CRYPTO_refcount_t)-1 == CRYPTO_REFCOUNT_MAX, + CRYPTO_REFCOUNT_MAX_is_incorrect); + +static struct CRYPTO_STATIC_MUTEX g_refcount_lock = CRYPTO_STATIC_MUTEX_INIT; + +void CRYPTO_refcount_inc(CRYPTO_refcount_t *count) { + CRYPTO_STATIC_MUTEX_lock_write(&g_refcount_lock); + if (*count < CRYPTO_REFCOUNT_MAX) { + (*count)++; + } + CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock); +} + +int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count) { + int ret; + + CRYPTO_STATIC_MUTEX_lock_write(&g_refcount_lock); + if (*count == 0) { + abort(); + } + if (*count < CRYPTO_REFCOUNT_MAX) { + (*count)--; + } + ret = (*count == 0); + CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock); + + return ret; +} + +#endif /* OPENSSL_C11_ATOMIC */ diff --git a/external/boringssl/crypto/refcount_test.c b/external/boringssl/crypto/refcount_test.c new file mode 100644 index 0000000000..97bfbd6fa1 --- /dev/null +++ b/external/boringssl/crypto/refcount_test.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#include + +#include + + +int main(int argc, char **argv) { + CRYPTO_refcount_t count = 0; + + CRYPTO_refcount_inc(&count); + if (count != 1) { + fprintf(stderr, "Incrementing reference count did not work.\n"); + return 1; + } + if (!CRYPTO_refcount_dec_and_test_zero(&count) || count != 0) { + fprintf(stderr, "Decrementing reference count to zero did not work.\n"); + return 1; + } + + count = CRYPTO_REFCOUNT_MAX; + CRYPTO_refcount_inc(&count); + if (count != CRYPTO_REFCOUNT_MAX) { + fprintf(stderr, "Count did not saturate correctly when incrementing.\n"); + return 1; + } + if (CRYPTO_refcount_dec_and_test_zero(&count) || + count != CRYPTO_REFCOUNT_MAX) { + fprintf(stderr, "Count did not saturate correctly when decrementing.\n"); + return 1; + } + + count = 2; + if (CRYPTO_refcount_dec_and_test_zero(&count)) { + fprintf(stderr, "Decrementing two resulted in zero!\n"); + return 1; + } + if (count != 1) { + fprintf(stderr, "Decrementing two did not produce one!"); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/rsa/CMakeLists.txt b/external/boringssl/crypto/rsa/CMakeLists.txt new file mode 100644 index 0000000000..23db9a7aae --- /dev/null +++ b/external/boringssl/crypto/rsa/CMakeLists.txt @@ -0,0 +1,26 @@ +include_directories(../../include) + +add_library( + rsa + + OBJECT + + rsa.c + rsa_impl.c + blinding.c + padding.c + rsa_asn1.c +) + +if(ENABLE_TESTS) +add_executable( + rsa_test + + rsa_test.cc + + $ +) + +target_link_libraries(rsa_test crypto) +add_dependencies(all_tests rsa_test) +endif() \ No newline at end of file diff --git a/external/boringssl/crypto/rsa/blinding.c b/external/boringssl/crypto/rsa/blinding.c new file mode 100644 index 0000000000..d9d90c2b47 --- /dev/null +++ b/external/boringssl/crypto/rsa/blinding.c @@ -0,0 +1,267 @@ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + +#include "internal.h" + + +#define BN_BLINDING_COUNTER 32 + +struct bn_blinding_st { + BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */ + BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */ + unsigned counter; +}; + +static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx); + +BN_BLINDING *BN_BLINDING_new(void) { + BN_BLINDING *ret = OPENSSL_malloc(sizeof(BN_BLINDING)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(BN_BLINDING)); + + ret->A = BN_new(); + if (ret->A == NULL) { + goto err; + } + + ret->Ai = BN_new(); + if (ret->Ai == NULL) { + goto err; + } + + /* The blinding values need to be created before this blinding can be used. */ + ret->counter = BN_BLINDING_COUNTER - 1; + + return ret; + +err: + BN_BLINDING_free(ret); + return NULL; +} + +void BN_BLINDING_free(BN_BLINDING *r) { + if (r == NULL) { + return; + } + + BN_free(r->A); + BN_free(r->Ai); + OPENSSL_free(r); +} + +static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + if (++b->counter == BN_BLINDING_COUNTER) { + /* re-create blinding parameters */ + if (!bn_blinding_create_param(b, e, mont, ctx)) { + goto err; + } + b->counter = 0; + } else { + if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) || + !BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) { + goto err; + } + } + + return 1; + +err: + /* |A| and |Ai| may be in an inconsistent state so they both need to be + * replaced the next time this blinding is used. Note that this is only + * sufficient because support for |BN_BLINDING_NO_UPDATE| and + * |BN_BLINDING_NO_RECREATE| was previously dropped. */ + b->counter = BN_BLINDING_COUNTER - 1; + + return 0; +} + +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery| + * cancels one Montgomery factor, so the resulting value of |n| is unencoded. + */ + if (!bn_blinding_update(b, e, mont, ctx) || + !BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) { + return 0; + } + + return 1; +} + +int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont, + BN_CTX *ctx) { + /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery| + * cancels one Montgomery factor, so the resulting value of |n| is unencoded. + */ + return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx); +} + +static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + BIGNUM mont_N_consttime; + BN_init(&mont_N_consttime); + BN_with_flags(&mont_N_consttime, &mont->N, BN_FLG_CONSTTIME); + int retry_counter = 32; + + do { + if (!BN_rand_range(b->A, &mont->N)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* |BN_from_montgomery| + |BN_mod_inverse_no_branch| is equivalent to, but + * more efficient than, |BN_mod_inverse_no_branch| + |BN_to_montgomery|. */ + if (!BN_from_montgomery(b->Ai, b->A, mont, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + int no_inverse; + if (BN_mod_inverse_ex(b->Ai, &no_inverse, b->Ai, &mont_N_consttime, ctx) == + NULL) { + /* this should almost never happen for good RSA keys */ + if (no_inverse) { + if (retry_counter-- == 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS); + return 0; + } + ERR_clear_error(); + } else { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + break; + } + } while (1); + + if (!BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!BN_to_montgomery(b->A, b->A, mont, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/rsa/internal.h b/external/boringssl/crypto/rsa/internal.h new file mode 100644 index 0000000000..c6ea97f09b --- /dev/null +++ b/external/boringssl/crypto/rsa/internal.h @@ -0,0 +1,148 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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 + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Default implementations of RSA operations. */ + +extern const RSA_METHOD RSA_default_method; + +size_t rsa_default_size(const RSA *rsa); +int rsa_default_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 rsa_default_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 rsa_default_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 rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, + size_t len); +int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes, + BIGNUM *e_value, BN_GENCB *cb); +int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb); + + +#define RSA_PKCS1_PADDING_SIZE 11 + + +BN_BLINDING *BN_BLINDING_new(void); +void BN_BLINDING_free(BN_BLINDING *b); +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont_ctx, BN_CTX *ctx); +int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx, + BN_CTX *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); + +/* 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); + + +/* RSA_additional_prime contains information about the third, forth etc prime + * in a multi-prime RSA key. */ +typedef struct RSA_additional_prime_st { + BIGNUM *prime; + /* exp is d^{prime-1} mod prime */ + BIGNUM *exp; + /* coeff is such that r×coeff ≡ 1 mod prime. */ + BIGNUM *coeff; + + /* Values below here are not in the ASN.1 serialisation. */ + + /* r is the product of all primes (including p and q) prior to this one. */ + BIGNUM *r; + /* mont is a |BN_MONT_CTX| modulo |prime|. */ + BN_MONT_CTX *mont; +} RSA_additional_prime; + +void RSA_additional_prime_free(RSA_additional_prime *ap); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_RSA_INTERNAL_H */ diff --git a/external/boringssl/crypto/rsa/padding.c b/external/boringssl/crypto/rsa/padding.c new file mode 100644 index 0000000000..12147ea4f8 --- /dev/null +++ b/external/boringssl/crypto/rsa/padding.c @@ -0,0 +1,706 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2005. + */ +/* ==================================================================== + * Copyright (c) 2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.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 to_len, + const uint8_t *from, unsigned from_len) { + unsigned j; + + if (to_len < RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + uint8_t *p = to; + + *(p++) = 0; + *(p++) = 1; /* Private Key BT (Block Type) */ + + /* pad out with 0xff data */ + j = to_len - 3 - from_len; + memset(p, 0xff, j); + p += j; + *(p++) = 0; + memcpy(p, from, from_len); + return 1; +} + +int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len) { + unsigned i, j; + const uint8_t *p; + + if (from_len < 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL); + return -1; + } + + p = from; + if ((*(p++) != 0) || (*(p++) != 1)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BLOCK_TYPE_IS_NOT_01); + return -1; + } + + /* scan over padding data */ + j = from_len - 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_R_BAD_FIXED_HEADER_DECRYPT); + return -1; + } + } + p++; + } + + if (i == j) { + OPENSSL_PUT_ERROR(RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING); + return -1; + } + + if (i < 8) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_PAD_BYTE_COUNT); + return -1; + } + i++; /* Skip over the '\0' */ + j -= i; + if (j > to_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); + return -1; + } + memcpy(to, p, j); + + return j; +} + +int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len) { + unsigned i, j; + + if (to_len < RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + uint8_t *p = to; + + *(p++) = 0; + *(p++) = 2; /* Public Key BT (Block Type) */ + + /* pad out with non-zero random data */ + j = to_len - 3 - from_len; + + 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, from_len); + return 1; +} + +int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len) { + if (from_len == 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY); + return -1; + } + + /* 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. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return -1; + } + + unsigned first_byte_is_zero = constant_time_eq(from[0], 0); + unsigned second_byte_is_two = constant_time_eq(from[1], 2); + + unsigned i, zero_index = 0, looking_for_index = ~0u; + for (i = 2; i < from_len; i++) { + unsigned equals0 = constant_time_is_zero(from[i]); + zero_index = constant_time_select(looking_for_index & equals0, (unsigned)i, + zero_index); + looking_for_index = constant_time_select(equals0, 0, looking_for_index); + } + + /* The input must begin with 00 02. */ + unsigned 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_ge(zero_index, 2 + 8); + + /* Skip the zero byte. */ + zero_index++; + + /* NOTE: Although this logic attempts to be constant time, the API contracts + * of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it + * impossible to completely avoid Bleichenbacher's attack. Consumers should + * use |RSA_unpad_key_pkcs1|. */ + if (!valid_index) { + OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR); + return -1; + } + + const unsigned msg_len = from_len - zero_index; + if (msg_len > to_len) { + /* This shouldn't happen because this function is always called with + * |to_len| as the key size and |from_len| is bounded by the key size. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR); + return -1; + } + + if (msg_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + + memcpy(to, &from[zero_index], msg_len); + return (int)msg_len; +} + +int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from, + unsigned from_len) { + if (from_len > to_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + if (from_len < to_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE); + return 0; + } + + memcpy(to, from, from_len); + return 1; +} + +static 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 to_len, + const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned param_len, + 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 (to_len < 2 * mdlen + 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + emlen = to_len - 1; + if (from_len > emlen - 2 * mdlen - 1) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + if (emlen < 2 * mdlen + 1) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + to[0] = 0; + seed = to + 1; + db = to + mdlen + 1; + + if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) { + return 0; + } + memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1); + db[emlen - from_len - mdlen - 1] = 0x01; + memcpy(db + emlen - from_len - mdlen, from, from_len); + if (!RAND_bytes(seed, mdlen)) { + return 0; + } + + dbmask = OPENSSL_malloc(emlen - mdlen); + if (dbmask == NULL) { + OPENSSL_PUT_ERROR(RSA, 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: + OPENSSL_free(dbmask); + return ret; +} + +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 param_len, + const EVP_MD *md, const EVP_MD *mgf1md) { + unsigned i, dblen, mlen = -1, mdlen, bad, looking_for_one_byte, one_index = 0; + const uint8_t *maskeddb, *maskedseed; + uint8_t *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE]; + + 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 (from_len < 1 + 2*mdlen + 1) { + /* 'from_len' is the length of the modulus, i.e. does not depend on the + * particular ciphertext. */ + goto decoding_err; + } + + dblen = from_len - mdlen - 1; + db = OPENSSL_malloc(dblen); + if (db == NULL) { + OPENSSL_PUT_ERROR(RSA, 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(param, param_len, phash, NULL, md, NULL)) { + goto err; + } + + bad = ~constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); + bad |= ~constant_time_is_zero(from[0]); + + looking_for_one_byte = ~0u; + for (i = mdlen; i < dblen; i++) { + unsigned equals1 = constant_time_eq(db[i], 1); + unsigned equals0 = constant_time_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 (to_len < mlen) { + OPENSSL_PUT_ERROR(RSA, 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_R_OAEP_DECODING_ERROR); + err: + 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_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_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_R_DATA_TOO_LARGE); + goto err; + } + if (EM[emLen - 1] != 0xbc) { + OPENSSL_PUT_ERROR(RSA, RSA_R_LAST_OCTET_INVALID); + goto err; + } + maskedDBLen = emLen - hLen - 1; + H = EM + maskedDBLen; + DB = OPENSSL_malloc(maskedDBLen); + if (!DB) { + OPENSSL_PUT_ERROR(RSA, 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_R_SLEN_RECOVERY_FAILED); + goto err; + } + if (sLen >= 0 && (maskedDBLen - i) != sLen) { + OPENSSL_PUT_ERROR(RSA, 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_R_BAD_SIGNATURE); + ret = 0; + } else { + ret = 1; + } + +err: + 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_R_SLEN_CHECK_FAILED); + goto err; + } + + if (BN_is_zero(rsa->n)) { + OPENSSL_PUT_ERROR(RSA, 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_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + sLen = emLen - hLen - 2; + } else if (emLen < hLen + sLen + 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + if (sLen > 0) { + salt = OPENSSL_malloc(sLen); + if (!salt) { + OPENSSL_PUT_ERROR(RSA, 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: + OPENSSL_free(salt); + + return ret; +} diff --git a/external/boringssl/crypto/rsa/rsa.c b/external/boringssl/crypto/rsa/rsa.c new file mode 100644 index 0000000000..e5f98916fb --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa.c @@ -0,0 +1,794 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +RSA *RSA_new(void) { return RSA_new_method(NULL); } + +RSA *RSA_new_method(const ENGINE *engine) { + RSA *rsa = OPENSSL_malloc(sizeof(RSA)); + if (rsa == NULL) { + OPENSSL_PUT_ERROR(RSA, 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; + CRYPTO_MUTEX_init(&rsa->lock); + CRYPTO_new_ex_data(&rsa->ex_data); + + if (rsa->meth->init && !rsa->meth->init(rsa)) { + CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data); + CRYPTO_MUTEX_cleanup(&rsa->lock); + METHOD_unref(rsa->meth); + OPENSSL_free(rsa); + return NULL; + } + + return rsa; +} + +void RSA_additional_prime_free(RSA_additional_prime *ap) { + if (ap == NULL) { + return; + } + + BN_clear_free(ap->prime); + BN_clear_free(ap->exp); + BN_clear_free(ap->coeff); + BN_clear_free(ap->r); + BN_MONT_CTX_free(ap->mont); + OPENSSL_free(ap); +} + +void RSA_free(RSA *rsa) { + unsigned u; + + if (rsa == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&rsa->references)) { + return; + } + + if (rsa->meth->finish) { + rsa->meth->finish(rsa); + } + METHOD_unref(rsa->meth); + + CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data); + + BN_clear_free(rsa->n); + BN_clear_free(rsa->e); + BN_clear_free(rsa->d); + BN_clear_free(rsa->p); + BN_clear_free(rsa->q); + BN_clear_free(rsa->dmp1); + BN_clear_free(rsa->dmq1); + BN_clear_free(rsa->iqmp); + BN_MONT_CTX_free(rsa->mont_n); + BN_MONT_CTX_free(rsa->mont_p); + BN_MONT_CTX_free(rsa->mont_q); + for (u = 0; u < rsa->num_blindings; u++) { + BN_BLINDING_free(rsa->blindings[u]); + } + OPENSSL_free(rsa->blindings); + OPENSSL_free(rsa->blindings_inuse); + if (rsa->additional_primes != NULL) { + sk_RSA_additional_prime_pop_free(rsa->additional_primes, + RSA_additional_prime_free); + } + CRYPTO_MUTEX_cleanup(&rsa->lock); + OPENSSL_free(rsa); +} + +int RSA_up_ref(RSA *rsa) { + CRYPTO_refcount_inc(&rsa->references); + 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_keygen(rsa, bits, e_value, cb); +} + +int RSA_generate_multi_prime_key(RSA *rsa, int bits, int num_primes, + BIGNUM *e_value, BN_GENCB *cb) { + if (rsa->meth->multi_prime_keygen) { + return rsa->meth->multi_prime_keygen(rsa, bits, num_primes, e_value, cb); + } + + return rsa_default_multi_prime_keygen(rsa, bits, num_primes, 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_encrypt(rsa, out_len, out, max_out, in, in_len, padding); +} + +int RSA_public_encrypt(size_t 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; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + 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_sign_raw(rsa, out_len, out, max_out, in, in_len, padding); +} + +int RSA_private_encrypt(size_t 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; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + 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_decrypt(rsa, out_len, out, max_out, in, in_len, padding); +} + +int RSA_private_decrypt(size_t 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; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + return out_len; +} + +int RSA_public_decrypt(size_t 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; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + return out_len; +} + +unsigned RSA_size(const RSA *rsa) { + if (rsa->meth->size) { + return rsa->meth->size(rsa); + } + + return rsa_default_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_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +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_undef, 0, {0}, + }, +}; + +int RSA_add_pkcs1_prefix(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; + + 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_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) { + continue; + } + + const uint8_t* prefix = sig_prefix->bytes; + unsigned prefix_len = sig_prefix->len; + unsigned signed_msg_len; + uint8_t *signed_msg; + + signed_msg_len = prefix_len + msg_len; + if (signed_msg_len < prefix_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_LONG); + return 0; + } + + signed_msg = OPENSSL_malloc(signed_msg_len); + if (!signed_msg) { + OPENSSL_PUT_ERROR(RSA, 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; + } + + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return 0; +} + +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 (!RSA_add_pkcs1_prefix(&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_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) { + if (rsa->n == NULL || rsa->e == NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + + 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 (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) { + OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH); + return 0; + } + + buf = OPENSSL_malloc(rsa_size); + if (!buf) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!RSA_verify_raw(rsa, &len, buf, rsa_size, sig, sig_len, + RSA_PKCS1_PADDING)) { + goto out; + } + + if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len, + &signed_msg_is_alloced, hash_nid, msg, msg_len)) { + goto out; + } + + if (len != signed_msg_len || memcmp(buf, signed_msg, len) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE); + goto out; + } + + ret = 1; + +out: + OPENSSL_free(buf); + if (signed_msg_is_alloced) { + OPENSSL_free(signed_msg); + } + return ret; +} + +static void bn_free_and_null(BIGNUM **bn) { + 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_R_ONLY_ONE_OF_P_Q_GIVEN); + return 0; + } + + if (!key->n || !key->e) { + OPENSSL_PUT_ERROR(RSA, 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, 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 (!BN_mul(&n, key->p, key->q, ctx) || + /* lcm = lcm(prime-1, for all primes) */ + !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)) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + goto out; + } + + size_t num_additional_primes = 0; + if (key->additional_primes != NULL) { + num_additional_primes = sk_RSA_additional_prime_num(key->additional_primes); + } + + size_t i; + for (i = 0; i < num_additional_primes; i++) { + const RSA_additional_prime *ap = + sk_RSA_additional_prime_value(key->additional_primes, i); + if (!BN_mul(&n, &n, ap->prime, ctx) || + !BN_sub(&pm1, ap->prime, BN_value_one()) || + !BN_mul(&lcm, &lcm, &pm1, ctx) || + !BN_gcd(&gcd, &gcd, &pm1, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + goto out; + } + } + + if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) || + !BN_gcd(&gcd, &pm1, &qm1, ctx) || + /* de = d*e mod lcm(prime-1, for all primes). */ + !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + goto out; + } + + if (BN_cmp(&n, key->n) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_N_NOT_EQUAL_P_Q); + goto out; + } + + if (!BN_is_one(&de)) { + OPENSSL_PUT_ERROR(RSA, 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_R_INCONSISTENT_SET_OF_CRT_VALUES); + goto out; + } + + if (has_crt_values && num_additional_primes == 0) { + 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, 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_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_R_EMPTY_PUBLIC_KEY); + return 0; + } + + if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) { + OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_PARAMS_ALREADY_GIVEN); + return 0; + } + + if (rsa->additional_primes != NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY); + 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, 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, 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, ERR_R_BN_LIB); + goto err; + } + + if (!BN_is_zero(rem)) { + OPENSSL_PUT_ERROR(RSA, 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, 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, ERR_R_BN_LIB); + goto err; + } + + if (BN_cmp(multiple, rsa->n) != 0) { + OPENSSL_PUT_ERROR(RSA, 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, 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_private_transform(rsa, out, in, len); +} + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) { + return 1; +} diff --git a/external/boringssl/crypto/rsa/rsa_asn1.c b/external/boringssl/crypto/rsa/rsa_asn1.c new file mode 100644 index 0000000000..d14ecaee9a --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa_asn1.c @@ -0,0 +1,445 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../bytestring/internal.h" + + +static int parse_integer_buggy(CBS *cbs, BIGNUM **out, int buggy) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + if (buggy) { + return BN_parse_asn1_unsigned_buggy(cbs, *out); + } + return BN_parse_asn1_unsigned(cbs, *out); +} + +static int parse_integer(CBS *cbs, BIGNUM **out) { + return parse_integer_buggy(cbs, out, 0 /* not buggy */); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* An RSA object may be missing some components. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + return BN_marshal_asn1(cbb, bn); +} + +static RSA *parse_public_key(CBS *cbs, int buggy) { + RSA *ret = RSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer_buggy(&child, &ret->n, buggy) || + !parse_integer(&child, &ret->e) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + + if (!BN_is_odd(ret->e) || + BN_num_bits(ret->e) < 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS); + RSA_free(ret); + return NULL; + } + + return ret; +} + +RSA *RSA_parse_public_key(CBS *cbs) { + return parse_public_key(cbs, 0 /* not buggy */); +} + +RSA *RSA_parse_public_key_buggy(CBS *cbs) { + /* Estonian IDs issued between September 2014 to September 2015 are + * broken. See https://crbug.com/532048 and https://crbug.com/534766. + * + * TODO(davidben): Remove this code and callers in March 2016. */ + return parse_public_key(cbs, 1 /* buggy */); +} + +RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +int RSA_marshal_public_key(CBB *cbb, const RSA *rsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, rsa->n) || + !marshal_integer(&child, rsa->e) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !RSA_marshal_public_key(&cbb, rsa) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +/* kVersionTwoPrime and kVersionMulti are the supported values of the version + * field of an RSAPrivateKey structure (RFC 3447). */ +static const uint64_t kVersionTwoPrime = 0; +static const uint64_t kVersionMulti = 1; + +/* rsa_parse_additional_prime parses a DER-encoded OtherPrimeInfo from |cbs| and + * advances |cbs|. It returns a newly-allocated |RSA_additional_prime| on + * success or NULL on error. The |r| and |mont| fields of the result are set to + * NULL. */ +static RSA_additional_prime *rsa_parse_additional_prime(CBS *cbs) { + RSA_additional_prime *ret = OPENSSL_malloc(sizeof(RSA_additional_prime)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(ret, 0, sizeof(RSA_additional_prime)); + + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->prime) || + !parse_integer(&child, &ret->exp) || + !parse_integer(&child, &ret->coeff) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_additional_prime_free(ret); + return NULL; + } + + return ret; +} + +RSA *RSA_parse_private_key(CBS *cbs) { + BN_CTX *ctx = NULL; + BIGNUM *product_of_primes_so_far = NULL; + RSA *ret = RSA_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + uint64_t version; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&child, &version)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + + if (version != kVersionTwoPrime && version != kVersionMulti) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_VERSION); + goto err; + } + + if (!parse_integer(&child, &ret->n) || + !parse_integer(&child, &ret->e) || + !parse_integer(&child, &ret->d) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->dmp1) || + !parse_integer(&child, &ret->dmq1) || + !parse_integer(&child, &ret->iqmp)) { + goto err; + } + + if (version == kVersionMulti) { + /* Although otherPrimeInfos is written as OPTIONAL in RFC 3447, it later + * says "[otherPrimeInfos] shall be omitted if version is 0 and shall + * contain at least one instance of OtherPrimeInfo if version is 1." The + * OPTIONAL is just so both versions share a single definition. */ + CBS other_prime_infos; + if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) || + CBS_len(&other_prime_infos) == 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + ret->additional_primes = sk_RSA_additional_prime_new_null(); + if (ret->additional_primes == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + ctx = BN_CTX_new(); + product_of_primes_so_far = BN_new(); + if (ctx == NULL || + product_of_primes_so_far == NULL || + !BN_mul(product_of_primes_so_far, ret->p, ret->q, ctx)) { + goto err; + } + + while (CBS_len(&other_prime_infos) > 0) { + RSA_additional_prime *ap = rsa_parse_additional_prime(&other_prime_infos); + if (ap == NULL) { + goto err; + } + if (!sk_RSA_additional_prime_push(ret->additional_primes, ap)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + RSA_additional_prime_free(ap); + goto err; + } + ap->r = BN_dup(product_of_primes_so_far); + if (ap->r == NULL || + !BN_mul(product_of_primes_so_far, product_of_primes_so_far, + ap->prime, ctx)) { + goto err; + } + } + } + + if (CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + + BN_CTX_free(ctx); + BN_free(product_of_primes_so_far); + return ret; + +err: + BN_CTX_free(ctx); + BN_free(product_of_primes_so_far); + RSA_free(ret); + return NULL; +} + +RSA *RSA_private_key_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + RSA *ret = RSA_parse_private_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +int RSA_marshal_private_key(CBB *cbb, const RSA *rsa) { + const int is_multiprime = + sk_RSA_additional_prime_num(rsa->additional_primes) > 0; + + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&child, + is_multiprime ? kVersionMulti : kVersionTwoPrime) || + !marshal_integer(&child, rsa->n) || + !marshal_integer(&child, rsa->e) || + !marshal_integer(&child, rsa->d) || + !marshal_integer(&child, rsa->p) || + !marshal_integer(&child, rsa->q) || + !marshal_integer(&child, rsa->dmp1) || + !marshal_integer(&child, rsa->dmq1) || + !marshal_integer(&child, rsa->iqmp)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + + if (is_multiprime) { + CBB other_prime_infos; + if (!CBB_add_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + size_t i; + for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + CBB other_prime_info; + if (!CBB_add_asn1(&other_prime_infos, &other_prime_info, + CBS_ASN1_SEQUENCE) || + !marshal_integer(&other_prime_info, ap->prime) || + !marshal_integer(&other_prime_info, ap->exp) || + !marshal_integer(&other_prime_info, ap->coeff)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + } + } + + if (!CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int RSA_private_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !RSA_marshal_private_key(&cbb, rsa) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + RSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !RSA_marshal_public_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + RSA *ret = RSA_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + RSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !RSA_marshal_private_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +RSA *RSAPublicKey_dup(const RSA *rsa) { + uint8_t *der; + size_t der_len; + if (!RSA_public_key_to_bytes(&der, &der_len, rsa)) { + return NULL; + } + RSA *ret = RSA_public_key_from_bytes(der, der_len); + OPENSSL_free(der); + return ret; +} + +RSA *RSAPrivateKey_dup(const RSA *rsa) { + uint8_t *der; + size_t der_len; + if (!RSA_private_key_to_bytes(&der, &der_len, rsa)) { + return NULL; + } + RSA *ret = RSA_private_key_from_bytes(der, der_len); + OPENSSL_free(der); + return ret; +} diff --git a/external/boringssl/crypto/rsa/rsa_impl.c b/external/boringssl/crypto/rsa/rsa_impl.c new file mode 100644 index 0000000000..af44a3d546 --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa_impl.c @@ -0,0 +1,1140 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +static int check_modulus_and_exponent_sizes(const RSA *rsa) { + unsigned rsa_bits = BN_num_bits(rsa->n); + + if (rsa_bits > 16 * 1024) { + OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE); + return 0; + } + + /* Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as + * the limit based on the recommendations in [1] and [2]. Windows CryptoAPI + * doesn't support values larger than 32 bits [3], so it is unlikely that + * exponents larger than 32 bits are being used for anything Windows commonly + * does. + * + * [1] https://www.imperialviolet.org/2012/03/16/rsae.html + * [2] https://www.imperialviolet.org/2012/03/17/rsados.html + * [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx */ + static const unsigned kMaxExponentBits = 33; + + if (BN_num_bits(rsa->e) > kMaxExponentBits) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE); + return 0; + } + + /* Verify |n > e|. Comparing |rsa_bits| to |kMaxExponentBits| is a small + * shortcut to comparing |n| and |e| directly. In reality, |kMaxExponentBits| + * is much smaller than the minimum RSA key size that any application should + * accept. */ + if (rsa_bits <= kMaxExponentBits) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + assert(BN_ucmp(rsa->n, rsa->e) > 0); + + return 1; +} + +size_t rsa_default_size(const RSA *rsa) { + return BN_num_bytes(rsa->n); +} + +int rsa_default_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 (max_out < rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!check_modulus_and_exponent_sizes(rsa)) { + 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, 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, 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, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) || + !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_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, 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) { + assert(ctx != NULL); + assert(rsa->mont_n != NULL); + + BN_BLINDING *ret = NULL; + BN_BLINDING **new_blindings; + uint8_t *new_blindings_inuse; + char overflow = 0; + + CRYPTO_MUTEX_lock_write(&rsa->lock); + + unsigned i; + for (i = 0; i < rsa->num_blindings; i++) { + if (rsa->blindings_inuse[i] == 0) { + rsa->blindings_inuse[i] = 1; + ret = rsa->blindings[i]; + *index_used = i; + break; + } + } + + if (ret != NULL) { + CRYPTO_MUTEX_unlock_write(&rsa->lock); + 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_MUTEX_unlock_write(&rsa->lock); + ret = BN_BLINDING_new(); + 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_MUTEX_lock_write(&rsa->lock); + + 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; + + OPENSSL_free(rsa->blindings); + rsa->blindings = new_blindings; + OPENSSL_free(rsa->blindings_inuse); + rsa->blindings_inuse = new_blindings_inuse; + rsa->num_blindings++; + + CRYPTO_MUTEX_unlock_write(&rsa->lock); + return ret; + +err2: + OPENSSL_free(new_blindings); + +err1: + CRYPTO_MUTEX_unlock_write(&rsa->lock); + 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_MUTEX_lock_write(&rsa->lock); + rsa->blindings_inuse[blinding_index] = 0; + CRYPTO_MUTEX_unlock_write(&rsa->lock); +} + +/* signing */ +int rsa_default_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, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + buf = OPENSSL_malloc(rsa_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(RSA, 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, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + + if (i <= 0) { + goto err; + } + + if (!RSA_private_transform(rsa, out, buf, rsa_size)) { + goto err; + } + + *out_len = rsa_size; + ret = 1; + +err: + if (buf != NULL) { + OPENSSL_cleanse(buf, rsa_size); + OPENSSL_free(buf); + } + + return ret; +} + +int rsa_default_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, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (padding == RSA_NO_PADDING) { + buf = out; + } else { + /* Allocate a temporary buffer to hold the padded plaintext. */ + buf = OPENSSL_malloc(rsa_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in_len != rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN); + goto err; + } + + if (!RSA_private_transform(rsa, buf, in, rsa_size)) { + 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_size; + break; + default: + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + + if (r < 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED); + } else { + *out_len = r; + ret = 1; + } + +err: + if (padding != RSA_NO_PADDING && buf != NULL) { + OPENSSL_cleanse(buf, rsa_size); + OPENSSL_free(buf); + } + + return ret; +} + +static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); + +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->n == NULL || rsa->e == NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + + const unsigned rsa_size = RSA_size(rsa); + BIGNUM *f, *result; + int r = -1; + + if (max_out < rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (in_len != rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN); + return 0; + } + + if (!check_modulus_and_exponent_sizes(rsa)) { + return 0; + } + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + + int ret = 0; + uint8_t *buf = NULL; + + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + if (f == NULL || result == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (padding == RSA_NO_PADDING) { + buf = out; + } else { + /* Allocate a temporary buffer to hold the padded plaintext. */ + buf = OPENSSL_malloc(rsa_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (BN_bin2bn(in, in_len, f) == NULL) { + goto err; + } + + if (BN_ucmp(f, rsa->n) >= 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) || + !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { + goto err; + } + + if (!BN_bn2bin_padded(buf, rsa_size, result)) { + OPENSSL_PUT_ERROR(RSA, 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_size; + break; + default: + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + + if (r < 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED); + } else { + *out_len = r; + ret = 1; + } + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + if (buf != out) { + OPENSSL_free(buf); + } + return ret; +} + +int rsa_default_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, 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, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* We cannot do blinding or verification without |e|, and continuing without + * those countermeasures is dangerous. However, the Java/Android RSA API + * requires support for keys where only |d| and |n| (and not |e|) are known. + * The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. */ + int disable_security = (rsa->flags & RSA_FLAG_NO_BLINDING) && rsa->e == NULL; + + if (!disable_security) { + /* Keys without public exponents must have blinding explicitly disabled to + * be used. */ + if (rsa->e == NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT); + goto err; + } + + blinding = rsa_blinding_get(rsa, &blinding_index, ctx); + if (blinding == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) { + goto err; + } + } + + if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL && + rsa->dmq1 != NULL && rsa->iqmp != NULL) { + if (!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 (!BN_mod_exp_mont_consttime(result, f, d, rsa->n, ctx, rsa->mont_n)) { + goto err; + } + } + + /* Verify the result to protect against fault attacks as described in the + * 1997 paper "On the Importance of Checking Cryptographic Protocols for + * Faults" by Dan Boneh, Richard A. DeMillo, and Richard J. Lipton. Some + * implementations do this only when the CRT is used, but we do it in all + * cases. Section 6 of the aforementioned paper describes an attack that + * works when the CRT isn't used. That attack is much less likely to succeed + * than the CRT attack, but there have likely been improvements since 1997. + * + * This check is cheap assuming |e| is small; it almost always is. */ + if (!disable_security) { + BIGNUM *vrfy = BN_CTX_get(ctx); + if (vrfy == NULL || + !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) || + !BN_equal_consttime(vrfy, f)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) { + goto err; + } + } + + if (!BN_bn2bin_padded(out, len, result)) { + OPENSSL_PUT_ERROR(RSA, 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) { + assert(ctx != NULL); + + assert(rsa->n != NULL); + assert(rsa->e != NULL); + assert(rsa->d != NULL); + assert(rsa->p != NULL); + assert(rsa->q != NULL); + assert(rsa->dmp1 != NULL); + assert(rsa->dmq1 != NULL); + assert(rsa->iqmp != NULL); + + BIGNUM *r1, *m1, *vrfy; + BIGNUM local_dmp1, local_dmq1, local_c, local_r1; + BIGNUM *dmp1, *dmq1, *c, *pr1; + int ret = 0; + size_t i, num_additional_primes = 0; + + if (rsa->additional_primes != NULL) { + num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes); + } + + BN_CTX_start(ctx); + r1 = BN_CTX_get(ctx); + m1 = BN_CTX_get(ctx); + vrfy = BN_CTX_get(ctx); + if (r1 == NULL || + m1 == NULL || + vrfy == NULL) { + goto err; + } + + { + BIGNUM local_p, local_q; + BIGNUM *p = NULL, *q = NULL; + + /* Make sure BN_mod_inverse in Montgomery intialization uses the + * BN_FLG_CONSTTIME flag. */ + 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 (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) || + !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx)) { + goto err; + } + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, 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 (!BN_mod_exp_mont_consttime(m1, r1, dmq1, rsa->q, ctx, rsa->mont_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 (!BN_mod_exp_mont_consttime(r0, r1, dmp1, rsa->p, ctx, rsa->mont_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; + } + + for (i = 0; i < num_additional_primes; i++) { + /* multi-prime RSA. */ + BIGNUM local_exp, local_prime; + BIGNUM *exp = &local_exp, *prime = &local_prime; + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + + BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME); + BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME); + + /* c will already point to a BIGNUM with the correct flags. */ + if (!BN_mod(r1, c, prime, ctx)) { + goto err; + } + + if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx) || + !BN_mod_exp_mont_consttime(m1, r1, exp, prime, ctx, ap->mont)) { + goto err; + } + + BN_set_flags(m1, BN_FLG_CONSTTIME); + + if (!BN_sub(m1, m1, r0) || + !BN_mul(m1, m1, ap->coeff, ctx) || + !BN_mod(m1, m1, prime, ctx) || + (BN_is_negative(m1) && !BN_add(m1, m1, prime)) || + !BN_mul(m1, m1, ap->r, ctx) || + !BN_add(r0, r0, m1)) { + goto err; + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes, + 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 prime_bits, ok = -1, n = 0, i, j; + BN_CTX *ctx = NULL; + STACK_OF(RSA_additional_prime) *additional_primes = NULL; + + if (num_primes < 2) { + ok = 0; /* we set our own err */ + OPENSSL_PUT_ERROR(RSA, RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES); + goto err; + } + + 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 (r0 == NULL || r1 == NULL || r2 == NULL || r3 == NULL) { + goto err; + } + + if (num_primes > 2) { + additional_primes = sk_RSA_additional_prime_new_null(); + if (additional_primes == NULL) { + goto err; + } + } + + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = OPENSSL_malloc(sizeof(RSA_additional_prime)); + if (ap == NULL) { + goto err; + } + memset(ap, 0, sizeof(RSA_additional_prime)); + ap->prime = BN_new(); + ap->exp = BN_new(); + ap->coeff = BN_new(); + ap->r = BN_new(); + if (ap->prime == NULL || + ap->exp == NULL || + ap->coeff == NULL || + ap->r == NULL || + !sk_RSA_additional_prime_push(additional_primes, ap)) { + RSA_additional_prime_free(ap); + goto err; + } + } + + /* We need the RSA components non-NULL */ + if (!rsa->n && ((rsa->n = BN_new()) == NULL)) { + goto err; + } + if (!rsa->d && ((rsa->d = BN_new()) == NULL)) { + goto err; + } + if (!rsa->e && ((rsa->e = BN_new()) == NULL)) { + goto err; + } + if (!rsa->p && ((rsa->p = BN_new()) == NULL)) { + goto err; + } + if (!rsa->q && ((rsa->q = BN_new()) == NULL)) { + goto err; + } + if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL)) { + goto err; + } + if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL)) { + goto err; + } + if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL)) { + goto err; + } + + if (!BN_copy(rsa->e, e_value)) { + goto err; + } + + /* generate p and q */ + prime_bits = (bits + (num_primes - 1)) / num_primes; + for (;;) { + if (!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb) || + !BN_sub(r2, rsa->p, BN_value_one()) || + !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; + } + prime_bits = ((bits - prime_bits) + (num_primes - 2)) / (num_primes - 1); + 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, prime_bits, 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, RSA_R_KEY_SIZE_TOO_SMALL); + goto err; + } + if (!BN_sub(r2, rsa->q, BN_value_one()) || + !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) || + !BN_mul(rsa->n, rsa->p, rsa->q, ctx)) { + goto err; + } + + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(additional_primes, i - 2); + prime_bits = ((bits - BN_num_bits(rsa->n)) + (num_primes - (i + 1))) / + (num_primes - i); + + for (;;) { + if (!BN_generate_prime_ex(ap->prime, prime_bits, 0, NULL, NULL, cb)) { + goto err; + } + if (BN_cmp(rsa->p, ap->prime) == 0 || + BN_cmp(rsa->q, ap->prime) == 0) { + continue; + } + + for (j = 0; j < i - 2; j++) { + if (BN_cmp(sk_RSA_additional_prime_value(additional_primes, j)->prime, + ap->prime) == 0) { + break; + } + } + if (j != i - 2) { + continue; + } + + if (!BN_sub(r2, ap->prime, BN_value_one()) || + !BN_gcd(r1, r2, rsa->e, ctx)) { + goto err; + } + + if (!BN_is_one(r1)) { + continue; + } + if (i != num_primes - 1) { + break; + } + + /* For the last prime we'll check that it makes n large enough. In the + * two prime case this isn't a problem because we generate primes with + * the top two bits set and so the product is always of the expected + * size. In the multi prime case, this doesn't follow. */ + if (!BN_mul(r1, rsa->n, ap->prime, ctx)) { + goto err; + } + if (BN_num_bits(r1) == (unsigned) bits) { + break; + } + + if (!BN_GENCB_call(cb, 2, n++)) { + goto err; + } + } + + /* ap->r is is the product of all the primes prior to the current one + * (including p and q). */ + if (!BN_copy(ap->r, rsa->n)) { + goto err; + } + if (i == num_primes - 1) { + /* In the case of the last prime, we calculated n as |r1| in the loop + * above. */ + if (!BN_copy(rsa->n, r1)) { + goto err; + } + } else if (!BN_mul(rsa->n, rsa->n, ap->prime, ctx)) { + 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 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) */ + } + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(additional_primes, i - 2); + if (!BN_sub(r3, ap->prime, BN_value_one()) || + !BN_mul(r0, r0, r3, ctx)) { + goto err; + } + } + 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; + } + + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(additional_primes, i - 2); + if (!BN_sub(ap->exp, ap->prime, BN_value_one()) || + !BN_mod(ap->exp, rsa->d, ap->exp, ctx) || + !BN_mod_inverse(ap->coeff, ap->r, ap->prime, ctx)) { + goto err; + } + } + + ok = 1; + rsa->additional_primes = additional_primes; + additional_primes = NULL; + +err: + if (ok == -1) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + ok = 0; + } + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + sk_RSA_additional_prime_pop_free(additional_primes, + RSA_additional_prime_free); + return ok; +} + +int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { + return rsa_default_multi_prime_keygen(rsa, bits, 2 /* num primes */, e_value, + cb); +} + +/* All of the methods are NULL to make it easier for the compiler/linker to drop + * unused functions. The wrapper functions will select the appropriate + * |rsa_default_*| implementation. */ +const RSA_METHOD RSA_default_method = { + { + 0 /* references */, + 1 /* is_static */, + }, + NULL /* app_data */, + + NULL /* init */, + NULL /* finish (defaults to rsa_default_finish) */, + + NULL /* size (defaults to rsa_default_size) */, + + NULL /* sign */, + NULL /* verify */, + + NULL /* encrypt (defaults to rsa_default_encrypt) */, + NULL /* sign_raw (defaults to rsa_default_sign_raw) */, + NULL /* decrypt (defaults to rsa_default_decrypt) */, + NULL /* verify_raw (defaults to rsa_default_verify_raw) */, + + NULL /* private_transform (defaults to rsa_default_private_transform) */, + + NULL /* mod_exp (ignored) */, + NULL /* bn_mod_exp (ignored) */, + + RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE, + + NULL /* keygen (defaults to rsa_default_keygen) */, + NULL /* multi_prime_keygen (defaults to rsa_default_multi_prime_keygen) */, + + NULL /* supports_digest */, +}; diff --git a/external/boringssl/crypto/rsa/rsa_test.cc b/external/boringssl/crypto/rsa/rsa_test.cc new file mode 100644 index 0000000000..62177a4c37 --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa_test.cc @@ -0,0 +1,954 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +// kPlaintext is a sample plaintext. +static const uint8_t kPlaintext[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; +static const size_t kPlaintextLen = sizeof(kPlaintext) - 1; + +// kKey1 is a DER-encoded RSAPrivateKey. +static const uint8_t kKey1[] = + "\x30\x82\x01\x38\x02\x01\x00\x02\x41\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\x02\x01\x11\x02\x40\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\x02" + "\x21\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\x02\x21" + "\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\x02\x20\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\x02\x21\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\x02\x20\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"; + +// kOAEPCiphertext1 is a sample encryption of |kPlaintext| with |kKey1| using +// RSA OAEP. +static const uint8_t kOAEPCiphertext1[] = + "\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"; + +// kKey2 is a DER-encoded RSAPrivateKey. +static const uint8_t kKey2[] = + "\x30\x81\xfb\x02\x01\x00\x02\x33\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\x02\x01\x03\x02\x32\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\x02\x1a\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\x02\x1a" + "\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\x02\x1a\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" + "\x02\x1a\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\x02\x1a\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"; + +// kOAEPCiphertext2 is a sample encryption of |kPlaintext| with |kKey2| using +// RSA OAEP. +static const uint8_t kOAEPCiphertext2[] = + "\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"; + +// kKey3 is a DER-encoded RSAPrivateKey. +static const uint8_t kKey3[] = + "\x30\x82\x02\x5b\x02\x01\x00\x02\x81\x81\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\x02\x01\x11\x02\x81" + "\x81\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\x02\x41\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\x02" + "\x41\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\x02\x40\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\x02\x40\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" + "\x02\x41\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"; + +// kOAEPCiphertext3 is a sample encryption of |kPlaintext| with |kKey3| using +// RSA OAEP. +static const uint8_t kOAEPCiphertext3[] = + "\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"; + +static const uint8_t kTwoPrimeKey[] = + "\x30\x82\x04\xa1\x02\x01\x00\x02\x82\x01\x01\x00\x93\x3a\x4f\xc9\x6a\x0a" + "\x6b\x28\x04\xfa\xb7\x05\x56\xdf\xa0\xaa\x4f\xaa\xab\x94\xa0\xa9\x25\xef" + "\xc5\x96\xd2\xd4\x66\x16\x62\x2c\x13\x7b\x91\xd0\x36\x0a\x10\x11\x6d\x7a" + "\x91\xb6\xe4\x74\x57\xc1\x3d\x7a\xbe\x24\x05\x3a\x04\x0b\x73\x91\x53\xb1" + "\x74\x10\xe1\x87\xdc\x91\x28\x9c\x1e\xe5\xf2\xb9\xfc\xa2\x48\x34\xb6\x78" + "\xed\x6d\x95\xfb\xf2\xc0\x4e\x1c\xa4\x15\x00\x3c\x8a\x68\x2b\xd6\xce\xd5" + "\xb3\x9f\x66\x02\xa7\x0d\x08\xa3\x23\x9b\xe5\x36\x96\x13\x22\xf9\x69\xa6" + "\x87\x88\x9b\x85\x3f\x83\x9c\xab\x1a\x1b\x6d\x8d\x16\xf4\x5e\xbd\xee\x4b" + "\x59\x56\xf8\x9d\x58\xcd\xd2\x83\x85\x59\x43\x84\x63\x4f\xe6\x1a\x86\x66" + "\x0d\xb5\xa0\x87\x89\xb6\x13\x82\x43\xda\x34\x92\x3b\x68\xc4\x95\x71\x2f" + "\x15\xc2\xe0\x43\x67\x3c\x08\x00\x36\x10\xc3\xb4\x46\x4c\x4e\x6e\xf5\x44" + "\xa9\x04\x44\x9d\xce\xc7\x05\x79\xee\x11\xcf\xaf\x2c\xd7\x9a\x32\xd3\xa5" + "\x30\xd4\x3a\x78\x43\x37\x74\x22\x90\x24\x04\x11\xd7\x95\x08\x52\xa4\x71" + "\x41\x68\x94\xb0\xa0\xc3\xec\x4e\xd2\xc4\x30\x71\x98\x64\x9c\xe3\x7c\x76" + "\xef\x33\xa3\x2b\xb1\x87\x63\xd2\x5c\x09\xfc\x90\x2d\x92\xf4\x57\x02\x01" + "\x03\x02\x82\x01\x00\x62\x26\xdf\xdb\x9c\x06\xf2\x1a\xad\xfc\x7a\x03\x8f" + "\x3f\xc0\x71\x8a\x71\xc7\xb8\x6b\x1b\x6e\x9f\xd9\x0f\x37\x38\x44\x0e\xec" + "\x1d\x62\x52\x61\x35\x79\x5c\x0a\xb6\x48\xfc\x61\x24\x98\x4d\x8f\xd6\x28" + "\xfc\x7e\xc2\xae\x26\xad\x5c\xf7\xb6\x37\xcb\xa2\xb5\xeb\xaf\xe8\x60\xc5" + "\xbd\x69\xee\xa1\xd1\x53\x16\xda\xcd\xce\xfb\x48\xf3\xb9\x52\xa1\xd5\x89" + "\x68\x6d\x63\x55\x7d\xb1\x9a\xc7\xe4\x89\xe3\xcd\x14\xee\xac\x6f\x5e\x05" + "\xc2\x17\xbd\x43\x79\xb9\x62\x17\x50\xf1\x19\xaf\xb0\x67\xae\x2a\x57\xbd" + "\xc7\x66\xbc\xf3\xb3\x64\xa1\xe3\x16\x74\x9e\xea\x02\x5c\xab\x94\xd8\x97" + "\x02\x42\x0c\x2c\xba\x54\xb9\xaf\xe0\x45\x93\xad\x7f\xb3\x10\x6a\x96\x50" + "\x4b\xaf\xcf\xc8\x27\x62\x2d\x83\xe9\x26\xc6\x94\xc1\xef\x5c\x8e\x06\x42" + "\x53\xe5\x56\xaf\xc2\x99\x01\xaa\x9a\x71\xbc\xe8\x21\x33\x2a\x2d\xa3\x36" + "\xac\x1b\x86\x19\xf8\xcd\x1f\x80\xa4\x26\x98\xb8\x9f\x62\x62\xd5\x1a\x7f" + "\xee\xdb\xdf\x81\xd3\x21\xdb\x33\x92\xee\xff\xe2\x2f\x32\x77\x73\x6a\x58" + "\xab\x21\xf3\xe3\xe1\xbc\x4f\x12\x72\xa6\xb5\xc2\xfb\x27\x9e\xc8\xca\xab" + "\x64\xa0\x87\x07\x9d\xef\xca\x0f\xdb\x02\x81\x81\x00\xe6\xd3\x4d\xc0\xa1" + "\x91\x0e\x62\xfd\xb0\xdd\xc6\x30\xb8\x8c\xcb\x14\xc1\x4b\x69\x30\xdd\xcd" + "\x86\x67\xcb\x37\x14\xc5\x03\xd2\xb4\x69\xab\x3d\xe5\x16\x81\x0f\xe5\x50" + "\xf4\x18\xb1\xec\xbc\x71\xe9\x80\x99\x06\xe4\xa3\xfe\x44\x84\x4a\x2d\x1e" + "\x07\x7f\x22\x70\x6d\x4f\xd4\x93\x0b\x8b\x99\xce\x1e\xab\xcd\x4c\xd2\xd3" + "\x10\x47\x5c\x09\x9f\x6d\x82\xc0\x08\x75\xe3\x3d\x83\xc2\x19\x50\x29\xec" + "\x1f\x84\x29\xcc\xf1\x56\xee\xbd\x54\x5d\xe6\x19\xdf\x0d\x1c\xa4\xbb\x0a" + "\xfe\x84\x44\x29\x1d\xf9\x5c\x80\x96\x5b\x24\xb4\xf7\x02\x1b\x02\x81\x81" + "\x00\xa3\x48\xf1\x9c\x58\xc2\x5f\x38\xfb\xd8\x12\x39\xf1\x8e\x73\xa1\xcf" + "\x78\x12\xe0\xed\x2a\xbb\xef\xac\x23\xb2\xbf\xd6\x0c\xe9\x6e\x1e\xab\xea" + "\x3f\x68\x36\xa7\x1f\xe5\xab\xe0\x86\xa5\x76\x32\x98\xdd\x75\xb5\x2b\xbc" + "\xcb\x8a\x03\x00\x7c\x2e\xca\xf8\xbc\x19\xe4\xe3\xa3\x31\xbd\x1d\x20\x2b" + "\x09\xad\x6f\x4c\xed\x48\xd4\xdf\x87\xf9\xf0\x46\xb9\x86\x4c\x4b\x71\xe7" + "\x48\x78\xdc\xed\xc7\x82\x02\x44\xd3\xa6\xb3\x10\x5f\x62\x81\xfc\xb8\xe4" + "\x0e\xf4\x1a\xdd\xab\x3f\xbc\x63\x79\x5b\x39\x69\x5e\xea\xa9\x15\xfe\x90" + "\xec\xda\x75\x02\x81\x81\x00\x99\xe2\x33\xd5\xc1\x0b\x5e\xec\xa9\x20\x93" + "\xd9\x75\xd0\x5d\xdc\xb8\x80\xdc\xf0\xcb\x3e\x89\x04\x45\x32\x24\xb8\x83" + "\x57\xe1\xcd\x9b\xc7\x7e\x98\xb9\xab\x5f\xee\x35\xf8\x10\x76\x9d\xd2\xf6" + "\x9b\xab\x10\xaf\x43\x17\xfe\xd8\x58\x31\x73\x69\x5a\x54\xc1\xa0\x48\xdf" + "\xe3\x0c\xb2\x5d\x11\x34\x14\x72\x88\xdd\xe1\xe2\x0a\xda\x3d\x5b\xbf\x9e" + "\x57\x2a\xb0\x4e\x97\x7e\x57\xd6\xbb\x8a\xc6\x9d\x6a\x58\x1b\xdd\xf6\x39" + "\xf4\x7e\x38\x3e\x99\x66\x94\xb3\x68\x6d\xd2\x07\x54\x58\x2d\x70\xbe\xa6" + "\x3d\xab\x0e\xe7\x6d\xcd\xfa\x01\x67\x02\x81\x80\x6c\xdb\x4b\xbd\x90\x81" + "\x94\xd0\xa7\xe5\x61\x7b\xf6\x5e\xf7\xc1\x34\xfa\xb7\x40\x9e\x1c\x7d\x4a" + "\x72\xc2\x77\x2a\x8e\xb3\x46\x49\x69\xc7\xf1\x7f\x9a\xcf\x1a\x15\x43\xc7" + "\xeb\x04\x6e\x4e\xcc\x65\xe8\xf9\x23\x72\x7d\xdd\x06\xac\xaa\xfd\x74\x87" + "\x50\x7d\x66\x98\x97\xc2\x21\x28\xbe\x15\x72\x06\x73\x9f\x88\x9e\x30\x8d" + "\xea\x5a\xa6\xa0\x2f\x26\x59\x88\x32\x4b\xef\x85\xa5\xe8\x9e\x85\x01\x56" + "\xd8\x8d\x19\xcc\xb5\x94\xec\x56\xa8\x7b\x42\xb4\xa2\xbc\x93\xc7\x7f\xd2" + "\xec\xfb\x92\x26\x46\x3f\x47\x1b\x63\xff\x0b\x48\x91\xa3\x02\x81\x80\x2c" + "\x4a\xb9\xa4\x46\x7b\xff\x50\x7e\xbf\x60\x47\x3b\x2b\x66\x82\xdc\x0e\x53" + "\x65\x71\xe9\xda\x2a\xb8\x32\x93\x42\xb7\xff\xea\x67\x66\xf1\xbc\x87\x28" + "\x65\x29\x79\xca\xab\x93\x56\xda\x95\xc1\x26\x44\x3d\x27\xc1\x91\xc6\x9b" + "\xd9\xec\x9d\xb7\x49\xe7\x16\xee\x99\x87\x50\x95\x81\xd4\x5c\x5b\x5a\x5d" + "\x0a\x43\xa5\xa7\x8f\x5a\x80\x49\xa0\xb7\x10\x85\xc7\xf4\x42\x34\x86\xb6" + "\x5f\x3f\x88\x9e\xc7\xf5\x59\x29\x39\x68\x48\xf2\xd7\x08\x5b\x92\x8e\x6b" + "\xea\xa5\x63\x5f\xc0\xfb\xe4\xe1\xb2\x7d\xb7\x40\xe9\x55\x06\xbf\x58\x25" + "\x6f"; + +static const uint8_t kTwoPrimeEncryptedMessage[] = { + 0x63, 0x0a, 0x30, 0x45, 0x43, 0x11, 0x45, 0xb7, 0x99, 0x67, 0x90, 0x35, + 0x37, 0x27, 0xff, 0xbc, 0xe0, 0xbf, 0xa6, 0xd1, 0x47, 0x50, 0xbb, 0x6c, + 0x1c, 0xaa, 0x66, 0xf2, 0xff, 0x9d, 0x9a, 0xa6, 0xb4, 0x16, 0x63, 0xb0, + 0xa1, 0x7c, 0x7c, 0x0c, 0xef, 0xb3, 0x66, 0x52, 0x42, 0xd7, 0x5e, 0xf3, + 0xa4, 0x15, 0x33, 0x40, 0x43, 0xe8, 0xb1, 0xfc, 0xe0, 0x42, 0x83, 0x46, + 0x28, 0xce, 0xde, 0x7b, 0x01, 0xeb, 0x28, 0x92, 0x70, 0xdf, 0x8d, 0x54, + 0x9e, 0xed, 0x23, 0xb4, 0x78, 0xc3, 0xca, 0x85, 0x53, 0x48, 0xd6, 0x8a, + 0x87, 0xf7, 0x69, 0xcd, 0x82, 0x8c, 0x4f, 0x5c, 0x05, 0x55, 0xa6, 0x78, + 0x89, 0xab, 0x4c, 0xd8, 0xa9, 0xd6, 0xa5, 0xf4, 0x29, 0x4c, 0x23, 0xc8, + 0xcf, 0xf0, 0x4c, 0x64, 0x6b, 0x4e, 0x02, 0x17, 0x69, 0xd6, 0x47, 0x83, + 0x30, 0x43, 0x02, 0x29, 0xda, 0xda, 0x75, 0x3b, 0xd7, 0xa7, 0x2b, 0x31, + 0xb3, 0xe9, 0x71, 0xa4, 0x41, 0xf7, 0x26, 0x9b, 0xcd, 0x23, 0xfa, 0x45, + 0x3c, 0x9b, 0x7d, 0x28, 0xf7, 0xf9, 0x67, 0x04, 0xba, 0xfc, 0x46, 0x75, + 0x11, 0x3c, 0xd5, 0x27, 0x43, 0x53, 0xb1, 0xb6, 0x9e, 0x18, 0xeb, 0x11, + 0xb4, 0x25, 0x20, 0x30, 0x0b, 0xe0, 0x1c, 0x17, 0x36, 0x22, 0x10, 0x0f, + 0x99, 0xb5, 0x50, 0x14, 0x73, 0x07, 0xf0, 0x2f, 0x5d, 0x4c, 0xe3, 0xf2, + 0x86, 0xc2, 0x05, 0xc8, 0x38, 0xed, 0xeb, 0x2a, 0x4a, 0xab, 0x76, 0xe3, + 0x1a, 0x75, 0x44, 0xf7, 0x6e, 0x94, 0xdc, 0x25, 0x62, 0x7e, 0x31, 0xca, + 0xc2, 0x73, 0x51, 0xb5, 0x03, 0xfb, 0xf9, 0xf6, 0xb5, 0x8d, 0x4e, 0x6c, + 0x21, 0x0e, 0xf9, 0x97, 0x26, 0x57, 0xf3, 0x52, 0x72, 0x07, 0xf8, 0xb4, + 0xcd, 0xb4, 0x39, 0xcf, 0xbf, 0x78, 0xcc, 0xb6, 0x87, 0xf9, 0xb7, 0x8b, + 0x6a, 0xce, 0x9f, 0xc8, +}; + +static const uint8_t kThreePrimeKey[] = + "\x30\x82\x04\xd7\x02\x01\x01\x02\x82\x01\x00\x62\x91\xe9\xea\xb3\x5d\x6c" + "\x29\xae\x21\x83\xbb\xb5\x82\xb1\x9e\xea\xe0\x64\x5b\x1e\x2f\x5e\x2c\x0a" + "\x80\x3d\x29\xd4\xfa\x9a\xe7\x44\xe6\x21\xbd\x98\xc0\x3d\xe0\x53\x59\xae" + "\xd3\x3e\xfe\xc4\xc2\xc4\x5a\x5a\x89\x07\xf4\x4f\xdc\xb0\x6a\xd4\x3e\x99" + "\x7d\x7a\x97\x26\x4e\xe1\x93\xca\x6e\xed\x07\xfc\xb4\xfa\x95\x1e\x73\x7b" + "\x86\x08\x6a\xb9\xd4\x29\xb0\x7e\x59\xb7\x9d\x7b\xeb\x67\x6e\xf0\xbb\x5e" + "\xcf\xb9\xcd\x58\x93\xf0\xe7\x88\x17\x6c\x0d\x76\x1e\xb9\x27\x9a\x4d\x02" + "\x16\xb6\x49\x6d\xa7\x83\x23\x4d\x02\x48\x0c\x0c\x1f\x0e\x85\x21\xe3\x06" + "\x76\x0a\x73\xe6\xc1\x21\xfa\x30\x18\x78\x29\x5c\x31\xd0\x29\xae\x6f\x7d" + "\x87\xd8\x2f\x16\xfa\xbc\x67\x8a\x94\x71\x59\x9b\xec\x22\x40\x55\x9f\xc2" + "\x94\xb5\xbd\x78\x01\xc9\xef\x18\xc8\x6d\x0d\xdc\x53\x42\xb2\x5c\xab\x65" + "\x05\xbd\x35\x08\x85\x1b\xf8\xe9\x47\xbc\xfe\xc5\xae\x47\x29\x63\x44\x8e" + "\x4d\xb7\x47\xab\x0d\xd8\x76\x68\x4f\xc7\x07\x02\xe4\x86\xb0\xcf\xd8\x19" + "\xad\xf4\x85\x76\x8b\x3b\x4e\x40\x8d\x29\x7a\x8a\x07\x36\xf3\x78\xae\x17" + "\xa6\x8f\x53\x58\x65\x4c\x86\x9e\xd7\x8b\xec\x38\x4f\x99\xc7\x02\x01\x03" + "\x02\x82\x01\x00\x41\xb6\x9b\xf1\xcc\xe8\xf2\xc6\x74\x16\x57\xd2\x79\x01" + "\xcb\xbf\x47\x40\x42\xe7\x69\x74\xe9\x72\xb1\xaa\xd3\x71\x38\xa7\x11\xef" + "\x83\x44\x16\x7e\x65\xd5\x7e\x95\x8c\xe6\x74\x8c\xd4\xa9\xd8\x81\xd8\x3c" + "\x3c\x5b\x5a\xa2\xdf\xe8\x75\x9c\x8d\x7f\x10\xfe\x51\xba\x19\x89\xeb\xb7" + "\xdc\x49\xf3\x5a\xa8\x78\xa7\x0e\x14\x4c\xfd\x04\x05\x9c\x7b\xe2\xc5\xa3" + "\x04\xee\xd9\x4c\xfd\x7d\x47\xb0\x0d\x9b\x3d\x70\x91\x81\x2c\xab\x2b\x87" + "\xad\x11\x68\x24\xfc\x2b\xd4\xee\x5e\x28\xeb\x6d\xab\xde\x0f\x77\x15\x58" + "\x76\x39\xc9\x59\x3a\x7f\x19\x9d\xc6\x7e\x86\xe4\xd5\x38\x70\x9e\xae\xb9" + "\xfb\x33\x33\xd1\x0c\x2d\xab\x01\x20\xe1\x8b\x29\x99\xd3\xeb\x87\x05\x72" + "\xaa\x43\x58\x64\x8e\x9e\x31\xdb\x45\x9b\x2b\xac\x58\x80\x5d\x33\xa2\x43" + "\x05\x96\xcc\xca\x2d\x04\x5f\xd6\xb7\x3d\x8b\x8f\x2d\xa3\xa5\xf8\x73\xf5" + "\xd7\xc0\x19\xff\x10\xe6\xee\x3a\x26\x2f\xe1\x64\x3d\x11\xcd\x2d\xe4\x0a" + "\x84\x27\xe3\xcb\x16\x62\x19\xe7\xe3\x0d\x13\xe8\x09\x5a\x53\xd0\x20\x56" + "\x15\xf5\xb3\x67\xac\xa1\xb5\x94\x6b\xab\xdc\x71\xc7\xbf\x0a\xde\x76\xf5" + "\x03\xa0\x30\xd8\x27\x9d\x00\x2b\x02\x57\x00\xf1\x4f\xc2\x86\x13\x06\x17" + "\xf7\x69\x7e\x37\xdf\x67\xc5\x32\xa0\x74\x1c\x32\x69\x0f\x9f\x08\x88\x24" + "\xb1\x51\xbc\xbc\x92\xba\x73\x1f\x9c\x75\xc2\x14\x6d\x4f\xc4\x5a\xcf\xda" + "\x44\x35\x00\x6b\x42\x3b\x9f\x14\xf1\x05\xb3\x51\x22\xb6\xbe\x9c\xe0\xc1" + "\x5c\x48\x61\xdf\x4e\x4c\x72\xb8\x05\x35\x7c\xac\xf1\xbb\xa0\x3b\x2a\xea" + "\xf7\x86\xe9\xd2\xff\x1e\x1d\x02\x56\x00\xca\xb1\x39\xf6\xa2\xc6\x3b\x65" + "\x45\x2f\x39\x00\xcd\x6e\xd6\x55\xf7\x71\x37\x89\xc2\xe7\x7a\xc0\x1a\xa6" + "\x2f\xea\x17\x7c\xaa\x2a\x91\x8f\xd4\xc7\x50\x8b\xab\x8e\x99\x3b\x33\x91" + "\xbc\x02\x10\x58\x4b\x58\x40\x9b\xc4\x8f\x48\x2b\xa7\x44\xfd\x07\x04\xf0" + "\x98\x67\x56\xea\x25\x92\x8b\x2e\x4b\x4a\xa1\xd3\xc2\xa4\xb4\x9b\x59\x70" + "\x32\xa6\xd8\x8b\xd9\x02\x57\x00\xa0\xdf\xd7\x04\x0c\xae\xba\xa4\xf0\xfe" + "\xcf\xea\x45\x2e\x21\xc0\x4d\x68\x21\x9b\x5f\xbf\x5b\x05\x6d\xcb\x8b\xd3" + "\x28\x61\xd1\xa2\x15\x12\xf9\x2c\x0d\x9e\x35\x2d\x91\xdf\xe6\xd8\x23\x55" + "\x9c\xd6\xd2\x6a\x0d\xf6\x03\xcc\xe0\xc1\xcf\x29\xbd\xeb\x2b\x92\xda\xeb" + "\xea\x34\x32\xf7\x25\x58\xce\x53\x1d\xf6\x7d\x15\x7c\xc7\x47\x4f\xaf\x46" + "\x8c\xaa\x14\x13\x02\x56\x00\x87\x20\xd1\x4f\x17\x2e\xd2\x43\x83\x74\xd0" + "\xab\x33\x9f\x39\x8e\xa4\xf6\x25\x06\x81\xef\xa7\x2a\xbc\x6e\xca\x9c\x0f" + "\xa8\x71\x71\xb6\x5f\xe3\x2f\x8b\x07\xc7\xb4\x66\x27\x77\xb6\x7d\x56\xb5" + "\x90\x32\x3a\xd5\xbd\x2d\xb4\xda\xc7\xc4\xd8\xa8\xaf\x58\xa0\x65\x9a\x39" + "\xf1\x6e\x61\xb2\x1e\xdc\xdc\x6b\xe2\x81\xc3\x23\x12\x3b\xa0\x21\xc4\x90" + "\x5d\x3b\x02\x57\x00\xe6\x8a\xaa\xb8\x6d\x2c\x81\x43\xb5\xd6\xa0\x2b\x42" + "\x49\xa9\x0a\x51\xfa\x18\xc8\x32\xea\x54\x18\xf3\x60\xc2\xb5\x4a\x43\x05" + "\x93\x9c\x01\xd9\x28\xed\x73\xfa\x82\xbc\x12\x64\xcb\xc4\x24\xa9\x3e\xae" + "\x7c\x4b\x8f\x94\x57\x7b\x14\x10\x41\xdc\x62\x12\x8c\xb2\x4a\x7c\xf6\x53" + "\xd4\xc6\xe4\xda\xd1\xa2\x00\x0e\x3d\x30\xf7\x05\x4f\x1d\x82\xbc\x52\xd9" + "\xb1\x30\x82\x01\x0a\x30\x82\x01\x06\x02\x56\x00\x84\x12\x4f\xf7\x3b\x65" + "\x53\x34\x6c\x6c\x4d\x77\xdf\xfd\x1f\xb6\x16\xe2\x25\x15\xca\xc9\xc1\x41" + "\x9a\x50\xda\xeb\x88\x4f\x3d\xb3\x01\x00\x44\xc4\xac\xe7\x14\x62\xa6\x56" + "\xde\xc5\xb7\xc3\x1d\x07\xbd\x7d\x64\xc5\x7e\x45\x25\x56\xed\x7a\xd2\x14" + "\xdb\x4e\x27\xd4\x1f\xf8\x94\xa7\xef\x07\xce\xdb\x24\xb7\xdd\x71\x5c\x63" + "\xc9\x33\xfe\xde\x40\x52\xeb\x02\x55\x58\x0c\x35\x4f\x7c\xee\x37\x78\x48" + "\x48\x33\xa5\x3f\xfe\x15\x24\x0f\x41\x6e\x0e\x87\x31\x2b\x81\x11\x8b\x3c" + "\x9d\x05\x8a\x29\x22\x00\xaa\xd8\x83\x1d\xef\x62\xec\x6e\xe4\x94\x83\xcf" + "\xd7\x68\xaf\xd3\xa8\xed\xd8\xfe\xd8\xc3\x8f\x48\xfc\x8c\x0d\xe7\x89\x6f" + "\xe2\xbf\xfb\x0d\xc5\x4a\x05\x34\x92\x18\x7a\x93\xa0\xe8\x42\x86\x22\xa9" + "\xe9\x80\x37\x47\x02\x55\x60\x76\xab\xde\x2b\xf5\xa2\x2c\xaa\x0c\x99\x81" + "\xee\x72\x2c\x7d\x22\x59\x2a\x35\xea\x50\x4e\x47\x6b\x92\x2d\x30\xa1\x01" + "\xa5\x9e\x26\x6e\x27\xca\xf5\xf2\x87\x5d\x31\xaf\xe9\x32\xcd\x10\xfd\x4d" + "\xdb\xf9\x86\x05\x12\x1b\x01\x84\x55\x97\x5f\xe2\x78\x27\xd9\xe4\x26\x7d" + "\xab\x0e\xe0\x1b\x6f\xcb\x4b\x14\xdd\xdc\xdc\x8b\xe8\x9f\xd0\x62\x96\xca" + "\xcf"; + +static const uint8_t kThreePrimeEncryptedMessage[] = { + 0x58, 0xd9, 0xea, 0x8a, 0xf6, 0x3d, 0xb4, 0xd9, 0xf7, 0xbb, 0x02, 0xc5, + 0x58, 0xd2, 0xa9, 0x46, 0x80, 0x70, 0x70, 0x16, 0x07, 0x64, 0x32, 0x4c, + 0x4e, 0x92, 0x61, 0xb7, 0xff, 0x92, 0xdc, 0xfc, 0xf8, 0xf0, 0x2c, 0x84, + 0x56, 0xbc, 0xe5, 0x93, 0x76, 0xe5, 0xa3, 0x72, 0x98, 0xf2, 0xdf, 0xef, + 0x99, 0x53, 0xf6, 0xd8, 0x4b, 0x09, 0xac, 0xa9, 0xa3, 0xdb, 0x63, 0xa1, + 0xb5, 0x09, 0x8e, 0x40, 0x84, 0x8f, 0x4d, 0xd5, 0x1d, 0xac, 0x6c, 0xaa, + 0x6b, 0x15, 0xe7, 0xb1, 0x0c, 0x67, 0xd2, 0xb2, 0x81, 0x58, 0x30, 0x0e, + 0x18, 0x27, 0xa1, 0x9b, 0x96, 0xad, 0xae, 0x76, 0x1a, 0x32, 0xf7, 0x10, + 0x0b, 0x53, 0x85, 0x31, 0xd6, 0x2a, 0xf6, 0x1c, 0x9f, 0xc2, 0xc7, 0xb1, + 0x05, 0x63, 0x0b, 0xa5, 0x07, 0x1f, 0x1c, 0x01, 0xf0, 0xe0, 0x06, 0xea, + 0x20, 0x69, 0x41, 0x19, 0x57, 0x92, 0x17, 0xf7, 0x0c, 0x5c, 0x66, 0x75, + 0x0e, 0xe5, 0xb3, 0xf1, 0x67, 0x3b, 0x27, 0x47, 0xb2, 0x8e, 0x1c, 0xb6, + 0x3f, 0xdd, 0x76, 0x42, 0x31, 0x13, 0x68, 0x96, 0xdf, 0x3b, 0xd4, 0x87, + 0xd9, 0x16, 0x44, 0x71, 0x52, 0x2e, 0x54, 0x3e, 0x09, 0xcd, 0x71, 0xc1, + 0x1e, 0x5e, 0x96, 0x13, 0xc9, 0x1e, 0xa4, 0xe6, 0xe6, 0x97, 0x2c, 0x6b, + 0xf2, 0xa9, 0x5c, 0xc6, 0x60, 0x2a, 0xbc, 0x82, 0xf8, 0xcb, 0xd4, 0xd7, + 0xea, 0x8a, 0xa1, 0x8a, 0xd9, 0xa5, 0x14, 0x8b, 0x9e, 0xf9, 0x25, 0x02, + 0xd2, 0xab, 0x0c, 0x42, 0xca, 0x2d, 0x45, 0xa3, 0x56, 0x5e, 0xa2, 0x2a, + 0xc8, 0x60, 0xa5, 0x87, 0x5d, 0x85, 0x5c, 0xde, 0xc7, 0xa2, 0x47, 0xc3, + 0x99, 0x29, 0x23, 0x79, 0x36, 0x88, 0xad, 0x40, 0x3e, 0x27, 0x7d, 0xf0, + 0xb6, 0xfa, 0x95, 0x20, 0x3c, 0xec, 0xfc, 0x56, 0x3b, 0x20, 0x91, 0xee, + 0x98, 0x10, 0x2c, 0x82, +}; + +static const uint8_t kSixPrimeKey[] = + "\x30\x82\x05\x20\x02\x01\x01\x02\x82\x01\x00\x1c\x04\x39\x44\xb9\xb8\x71" + "\x1c\x1c\xf7\xdc\x11\x1b\x85\x3b\x2b\xe8\xa6\xeb\xeb\xe9\xb6\x86\x97\x73" + "\x5d\x75\x46\xd1\x35\x25\xf8\x30\x9a\xc3\x57\x44\x89\xa6\x44\x59\xe3\x3a" + "\x60\xb5\x33\x84\x72\xa4\x03\xc5\x1a\x20\x98\x70\xbd\xe8\x3b\xc1\x9b\x8a" + "\x3a\x24\x45\xb6\x6a\x73\xb4\xd0\x6c\x18\xc6\xa7\x94\xd3\x24\x70\xf0\x2d" + "\x0c\xa5\xb2\x3b\xc5\x33\x90\x9d\x56\x8d\x33\xf6\x93\x7d\xa7\x95\x88\x05" + "\xdf\xf5\x65\x58\xb9\x5b\xd3\x07\x9c\x16\x8e\x74\xfc\xb8\x76\xaf\x62\x99" + "\x6c\xd4\xc5\xb3\x69\xe5\x64\xdf\x38\x00\x25\x24\xe9\xb1\x4a\x85\xa6\xf4" + "\xb6\x23\x68\x67\x4a\x2c\xbd\x9d\x01\x3b\x04\x8c\x70\x94\x82\x76\x45\x0c" + "\x8b\x95\x8a\x07\x1c\x32\xe7\x09\x97\x3a\xfd\xca\x57\xe9\x57\x0c\xae\x2b" + "\xa3\x25\xd1\xf2\x0d\x34\xa1\xe6\x2f\x7b\x1b\x36\x53\x83\x95\xb9\x26\x6e" + "\x4f\x36\x26\xf8\x47\xae\xdf\xe8\x4d\xf6\xb2\xff\x03\x23\x74\xfa\xa5\x6d" + "\xcb\xcb\x80\x12\xc3\x77\xf0\x19\xb7\xf2\x6b\x19\x5c\xde\x0a\xd7\xee\x8c" + "\x48\x2f\x50\x24\xa5\x2e\xcc\x2a\xed\xc2\x35\xe0\x3d\x29\x31\x17\xd6\x8f" + "\x44\xaa\x5b\x33\xbd\xb4\x88\x87\xd9\x29\x3f\x94\xe7\x75\xe3\x02\x01\x03" + "\x02\x82\x01\x00\x12\xad\x7b\x83\x26\x7a\xf6\x12\xbd\xfa\x92\xb6\x12\x58" + "\xd2\x1d\x45\xc4\x9d\x47\xf1\x24\x59\xba\x4c\xe8\xf8\xd9\xe0\xce\x19\x50" + "\x20\x67\x2c\xe4\xd8\x5b\xc4\x2d\x91\x41\xeb\x05\x4f\xf4\xb4\x20\xc7\xbc" + "\xd6\xe2\x5c\xa0\x27\xcf\xb8\xb3\x3b\x5c\xeb\x5e\x96\xb7\x99\x4b\x8a\xc3" + "\x70\xaf\x7f\xd8\x5f\xeb\xcb\x1a\x79\x44\x68\x97\x84\xd8\x29\x87\x64\xba" + "\x18\x2e\x95\x66\x1a\x7d\xd9\x35\x3a\x5c\x92\x7a\x81\x1b\x6c\xa9\xf8\xfa" + "\x05\x23\x18\x5b\xb2\xf8\x77\x1c\xc5\x1b\x7d\x26\x5f\x48\x69\x1b\xc4\x34" + "\xef\x6e\xa1\x15\xd2\xb2\xac\xb8\xa8\xed\x1e\xee\xdc\xb5\xb9\x5c\x79\x25" + "\x48\xbb\xe5\x9d\xd8\xe5\xe2\x94\xdf\xd5\x32\x22\x84\xbf\xc2\xaa\xa4\x54" + "\xbb\x29\xdb\x13\x4a\x28\x3d\x83\x3a\xff\xa3\xae\x38\x08\xfc\x36\x84\x91" + "\x30\xd1\xfd\x82\x64\xf1\x0f\xae\xba\xd7\x9a\x43\x58\x03\x5e\x5f\x01\xcb" + "\x8b\x90\x8d\x77\x34\x6f\x37\x40\xb6\x6d\x22\x23\x90\xb2\xfd\x32\xb5\x96" + "\x45\xbf\xae\x8c\xc4\x62\x03\x6c\x68\x90\x59\x31\x1a\xcb\xfb\xa4\x0b\x94" + "\x15\x13\xda\x1a\x8d\xa7\x0b\x34\x62\x93\xea\xbe\x6e\x71\xc2\x1d\xc8\x9d" + "\xac\x66\xcc\x31\x87\xff\x99\xab\x02\x2c\x00\xa5\x57\x41\x66\x87\x68\x02" + "\x6a\xdf\x97\xb0\xfe\x6b\x34\xc4\x33\x88\x2b\xce\x82\xaf\x2d\x33\x5a\xad" + "\x75\x2d\xac\xa5\xd6\x3a\x2d\x65\x43\x68\xfb\x44\x9e\xb8\x25\x05\xed\x97" + "\x02\x2c\x00\xd2\x77\x34\x24\xac\x60\x9a\xc4\x68\x34\xe5\x6a\xa3\xdc\xe2" + "\xb0\x58\x5c\x35\x83\x5a\xc7\xa7\xc1\x0b\x7e\x9e\xa5\x85\x32\x47\x93\x22" + "\xee\xb6\x59\xe9\xe3\x61\x94\xd0\x0e\xcb\x02\x2b\x6e\x3a\x2b\x99\xaf\x9a" + "\xac\x47\x3f\xba\x75\xfe\xf2\x23\x2d\x77\xb0\x1d\x34\x57\x1f\x73\x77\x91" + "\xc8\xf8\xc9\x1d\xc3\xe4\x26\xc8\xee\x2c\xf0\xa7\x83\x14\x7a\xc3\x59\x49" + "\x0f\x02\x2c\x00\x8c\x4f\x78\x18\x72\xeb\x11\xd8\x45\x78\x98\xf1\xc2\x93" + "\x41\xca\xe5\x92\xce\x57\x91\xda\x6f\xd6\x07\xa9\xbf\x19\x03\x76\xda\x62" + "\x17\x49\xce\xe6\x9b\xec\xeb\xb8\x8a\xb4\x87\x02\x2c\x00\xa3\xc2\x29\xa6" + "\xa7\xe1\x3c\xe9\xcf\x0f\x50\x51\x1c\xcc\xc8\x5b\x08\x9c\x97\x24\x3a\x86" + "\x23\xa8\x0b\xbb\x54\xa6\xb9\x70\x3d\x1d\xd0\x1b\xa3\xac\xd9\xb2\x03\x80" + "\xd7\x67\xec\x30\x82\x02\x29\x30\x81\x88\x02\x2c\x00\x97\x5d\x3b\xf2\xcc" + "\xba\xd9\x77\x67\xaa\xd2\x22\xa7\xa3\x49\x08\xc7\xb8\x27\xa1\x59\x4b\xa7" + "\xa5\xd2\x74\x05\xe7\x5a\x35\xd7\x25\x79\x18\x20\x8a\x25\xec\x3b\x52\xaf" + "\xcb\xdb\x02\x2b\x64\xe8\xd2\xa1\xdd\xd1\xe6\x4f\x9a\x71\xe1\x6c\x6f\xc2" + "\x30\xb0\x85\x25\x6f\xc0\xe6\x32\x6f\xc3\xe1\xa2\xae\x9a\x3c\x23\xe4\xc3" + "\xa6\x10\x15\xb1\x6e\x9d\x7c\xe1\xca\x87\xe7\x02\x2b\x5e\xef\x25\x29\xed" + "\xf6\x52\x15\xd3\x60\xb6\x88\xcf\x0f\xe2\x24\xa4\x04\x97\x9c\x9d\x58\x13" + "\xbb\x00\x6d\x39\xf6\xad\x21\x7e\x56\x2c\x2e\x06\x06\xc4\x6d\x44\xac\x79" + "\x1f\xe5\x30\x81\x89\x02\x2c\x00\xdb\xf1\x78\xf9\xa4\x94\xea\x39\x8a\x3f" + "\x23\x48\x2a\x23\x8f\xd2\x18\x97\xd2\xdf\x0f\xb8\x2b\x33\xa0\xe8\x8f\xbc" + "\x4e\x42\xfd\x54\xc7\x0f\xde\xba\x6d\xba\x96\xa7\xce\x67\x3d\x02\x2c\x00" + "\x92\xa0\xfb\x51\x18\x63\x46\xd1\x06\xd4\xc2\x30\x1c\x17\xb5\x36\xbb\x0f" + "\xe1\xea\x0a\x7a\xc7\x77\xc0\x9b\x0a\x7d\x89\x81\xfe\x38\x84\xb5\x3f\x26" + "\xf3\xd1\xb9\xc5\x34\x44\xd3\x02\x2b\x4c\xbd\x1d\x44\xc8\x19\x23\xd8\xb3" + "\x96\x66\x4b\x62\xcb\x3e\xe6\x6c\x11\xdf\xb2\x92\xd3\xc8\x34\xb9\xa6\x5a" + "\x2f\x19\xf4\x0b\xb2\xe6\x8e\xa6\xaf\xa3\xae\xa4\xb3\x92\xc4\x79\x30\x81" + "\x85\x02\x2b\x00\x89\xab\x30\xfc\x7b\x37\x94\x11\x9f\x4d\x31\x3b\xac\x09" + "\x57\xe6\x64\xec\xa0\xc8\xf8\x04\x1a\xf9\x2a\xa4\x4b\x36\x18\xbb\x5f\xdc" + "\xcd\xf0\xc8\xcb\x97\xd1\xdf\x13\x12\x3f\x02\x2a\x5b\xc7\x75\xfd\xa7\x7a" + "\x62\xb6\x6a\x33\x76\x27\xc8\x06\x3a\x99\x98\x9d\xc0\x85\xfa\xad\x67\x50" + "\xc7\x18\x32\x24\x10\x7c\xea\x93\x33\xf5\xdb\x32\x65\x36\x94\xb7\x61\x7f" + "\x02\x2a\x16\x6c\x96\xa1\x50\x6f\x3a\x92\xc0\x75\x43\xb5\x6b\x9c\x17\x09" + "\xd3\xf0\x67\x69\x45\x92\xfb\x7b\x50\xa8\x42\x9b\x33\x92\xab\xd5\xe6\x49" + "\xb3\x26\x99\x55\x16\x3a\x39\x63\x30\x81\x87\x02\x2b\x00\xc1\x25\x19\x1d" + "\x6e\x18\xcb\x2d\x64\xe2\xe6\xb6\x1c\xe4\xaa\x9c\xb9\xee\x18\xd4\xf7\x5f" + "\x66\x40\xf0\xe1\x31\x38\xf2\x53\x00\x8b\xcc\xe4\x0d\xb7\x81\xb4\xe6\x1c" + "\x19\xaf\x02\x2b\x00\x80\xc3\x66\x13\x9e\xbb\x32\x1e\x43\x41\xef\x24\x13" + "\x43\x1c\x68\x7b\xf4\x10\x8d\xfa\x3f\x99\x80\xa0\x96\x20\xd0\xa1\x8c\xab" + "\x07\xdd\xed\x5e\x7a\x56\x78\x99\x68\x11\x1f\x02\x2b\x00\xb0\x59\xea\x67" + "\x93\x42\xbf\x07\x54\x38\x41\xcb\x73\xa4\x0e\xc2\xae\x56\x19\x41\xc9\x8a" + "\xb2\x2f\xa8\x0a\xb1\x4e\x12\x39\x2e\xc0\x94\x9a\xc6\xa3\xe4\xaf\x8a\x16" + "\x06\xb8"; + +static const uint8_t kSixPrimeEncryptedMessage[] = { + 0x0a, 0xcb, 0x6c, 0x02, 0x9d, 0x1a, 0x7c, 0xf3, 0x4e, 0xff, 0x16, 0x88, + 0xee, 0x22, 0x1d, 0x8d, 0xd2, 0xfd, 0xde, 0x83, 0xb3, 0xd9, 0x35, 0x2c, + 0x82, 0xe0, 0xff, 0xe6, 0x79, 0x6d, 0x06, 0x21, 0x74, 0xa8, 0x04, 0x0c, + 0xe2, 0xd3, 0x98, 0x3f, 0xbf, 0xd0, 0xe9, 0x88, 0x24, 0xe2, 0x05, 0xa4, + 0x45, 0x51, 0x87, 0x6b, 0x1c, 0xef, 0x5f, 0x2d, 0x61, 0xb6, 0xf1, 0x4c, + 0x1f, 0x3d, 0xbf, 0x4b, 0xf2, 0xda, 0x09, 0x97, 0x81, 0xde, 0x91, 0xb7, + 0x0d, 0xb4, 0xc2, 0xab, 0x41, 0x64, 0x9d, 0xd9, 0x39, 0x46, 0x79, 0x66, + 0x43, 0xf1, 0x34, 0x21, 0x56, 0x2f, 0xc6, 0x68, 0x40, 0x4a, 0x2d, 0x73, + 0x96, 0x50, 0xe1, 0xb0, 0xaf, 0x49, 0x39, 0xb4, 0xf0, 0x3a, 0x78, 0x38, + 0x70, 0xa9, 0x91, 0x5d, 0x5e, 0x07, 0xf4, 0xec, 0xbb, 0xc4, 0xe5, 0x8a, + 0xb8, 0x06, 0xba, 0xdf, 0xc6, 0x48, 0x78, 0x4b, 0xca, 0x2a, 0x8a, 0x92, + 0x64, 0xe3, 0xa6, 0xae, 0x87, 0x97, 0x12, 0x16, 0x46, 0x67, 0x59, 0xdf, + 0xf2, 0xf3, 0x89, 0x6f, 0xe8, 0xa9, 0x13, 0x57, 0x63, 0x4e, 0x07, 0x98, + 0xcc, 0x73, 0xa0, 0x84, 0x9d, 0xe8, 0xb3, 0x50, 0x59, 0xb5, 0x51, 0xb3, + 0x41, 0x7d, 0x55, 0xfe, 0xd9, 0xf0, 0xc6, 0xff, 0x6e, 0x96, 0x4f, 0x22, + 0xb2, 0x0d, 0x6b, 0xc9, 0x83, 0x2d, 0x98, 0x98, 0xb2, 0xd1, 0xb7, 0xe4, + 0x50, 0x83, 0x1a, 0xa9, 0x02, 0x9f, 0xaf, 0x54, 0x74, 0x2a, 0x2c, 0x63, + 0x10, 0x79, 0x45, 0x5c, 0x95, 0x0d, 0xa1, 0x9b, 0x55, 0xf3, 0x1e, 0xb7, + 0x56, 0x59, 0xf1, 0x59, 0x8d, 0xd6, 0x15, 0x89, 0xf6, 0xfe, 0xc0, 0x00, + 0xdd, 0x1f, 0x2b, 0xf0, 0xf7, 0x5d, 0x64, 0x84, 0x76, 0xd3, 0xc2, 0x92, + 0x35, 0xac, 0xb5, 0xf9, 0xf6, 0xa8, 0x05, 0x89, 0x4c, 0x95, 0x41, 0x4e, + 0x34, 0x25, 0x11, 0x14, +}; + +// kEstonianRSAKey is an RSAPublicKey encoded with a negative modulus. See +// https://crbug.com/532048. +static const uint8_t kEstonianRSAKey[] = { + 0x30, 0x82, 0x01, 0x09, 0x02, 0x82, 0x01, 0x00, 0x96, 0xa6, 0x2e, 0x9c, + 0x4e, 0x6a, 0xc3, 0xcc, 0xcd, 0x8f, 0x70, 0xc3, 0x55, 0xbf, 0x5e, 0x9c, + 0xd4, 0xf3, 0x17, 0xc3, 0x97, 0x70, 0xae, 0xdf, 0x12, 0x5c, 0x15, 0x80, + 0x03, 0xef, 0x2b, 0x18, 0x9d, 0x6a, 0xcb, 0x52, 0x22, 0xc1, 0x81, 0xb8, + 0x7e, 0x61, 0xe8, 0x0f, 0x79, 0x24, 0x0f, 0x82, 0x70, 0x24, 0x4e, 0x29, + 0x20, 0x05, 0x54, 0xeb, 0xd4, 0xa9, 0x65, 0x59, 0xb6, 0x3c, 0x75, 0x95, + 0x2f, 0x4c, 0xf6, 0x9d, 0xd1, 0xaf, 0x5f, 0x14, 0x14, 0xe7, 0x25, 0xea, + 0xa5, 0x47, 0x5d, 0xc6, 0x3e, 0x28, 0x8d, 0xdc, 0x54, 0x87, 0x2a, 0x7c, + 0x10, 0xe9, 0xc6, 0x76, 0x2d, 0xe7, 0x79, 0xd8, 0x0e, 0xbb, 0xa9, 0xac, + 0xb5, 0x18, 0x98, 0xd6, 0x47, 0x6e, 0x06, 0x70, 0xbf, 0x9e, 0x82, 0x25, + 0x95, 0x4e, 0xfd, 0x70, 0xd7, 0x73, 0x45, 0x2e, 0xc1, 0x1f, 0x7a, 0x9a, + 0x9d, 0x60, 0xc0, 0x1f, 0x67, 0x06, 0x2a, 0x4e, 0x87, 0x3f, 0x19, 0x88, + 0x69, 0x64, 0x4d, 0x9f, 0x75, 0xf5, 0xd3, 0x1a, 0x41, 0x3d, 0x35, 0x17, + 0xb6, 0xd1, 0x44, 0x0d, 0x25, 0x8b, 0xe7, 0x94, 0x39, 0xb0, 0x7c, 0xaf, + 0x3e, 0x6a, 0xfa, 0x8d, 0x90, 0x21, 0x0f, 0x8a, 0x43, 0x94, 0x37, 0x7c, + 0x2a, 0x15, 0x4c, 0xa0, 0xfa, 0xa9, 0x2f, 0x21, 0xa6, 0x6f, 0x8e, 0x2f, + 0x89, 0xbc, 0xbb, 0x33, 0xf8, 0x31, 0xfc, 0xdf, 0xcd, 0x68, 0x9a, 0xbc, + 0x75, 0x06, 0x95, 0xf1, 0x3d, 0xef, 0xca, 0x76, 0x27, 0xd2, 0xba, 0x8e, + 0x0e, 0x1c, 0x43, 0xd7, 0x70, 0xb9, 0xc6, 0x15, 0xca, 0xd5, 0x4d, 0x87, + 0xb9, 0xd1, 0xae, 0xde, 0x69, 0x73, 0x00, 0x2a, 0x97, 0x51, 0x4b, 0x30, + 0x01, 0xc2, 0x85, 0xd0, 0x05, 0xcc, 0x2e, 0xe8, 0xc7, 0x42, 0xe7, 0x94, + 0x51, 0xe3, 0xf5, 0x19, 0x35, 0xdc, 0x57, 0x96, 0xe7, 0xd9, 0xb4, 0x49, + 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +// kExponent1RSAKey is an RSAPublicKey encoded with an exponent of 1. See +// https://crbug.com/541257 +static const uint8_t kExponent1RSAKey[] = { + 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xcf, 0x86, 0x9a, + 0x7d, 0x5c, 0x9f, 0xbd, 0x33, 0xbb, 0xc2, 0xb1, 0x06, 0xa8, 0x3e, 0xc5, + 0x18, 0xf3, 0x01, 0x04, 0xdd, 0x7a, 0x38, 0x0e, 0x8e, 0x8d, 0x10, 0xaa, + 0xf8, 0x64, 0x49, 0x82, 0xa6, 0x16, 0x9d, 0xd9, 0xae, 0x5e, 0x7f, 0x9b, + 0x53, 0xcb, 0xbb, 0x29, 0xda, 0x98, 0x47, 0x26, 0x88, 0x2e, 0x1d, 0x64, + 0xb3, 0xbc, 0x7e, 0x96, 0x3a, 0xa7, 0xd6, 0x87, 0xf6, 0xf5, 0x3f, 0xa7, + 0x3b, 0xd3, 0xc5, 0xd5, 0x61, 0x3c, 0x63, 0x05, 0xf9, 0xbc, 0x64, 0x1d, + 0x71, 0x65, 0xf5, 0xc8, 0xe8, 0x64, 0x41, 0x35, 0x88, 0x81, 0x6b, 0x2a, + 0x24, 0xbb, 0xdd, 0x9f, 0x75, 0x4f, 0xea, 0x35, 0xe5, 0x32, 0x76, 0x5a, + 0x8b, 0x7a, 0xb5, 0x92, 0x65, 0x34, 0xb7, 0x88, 0x42, 0x5d, 0x41, 0x0b, + 0xd1, 0x00, 0x2d, 0x43, 0x47, 0x55, 0x60, 0x3c, 0x0e, 0x60, 0x04, 0x5c, + 0x88, 0x13, 0xc7, 0x42, 0x55, 0x16, 0x31, 0x32, 0x81, 0xba, 0xde, 0xa9, + 0x56, 0xeb, 0xdb, 0x66, 0x7f, 0x31, 0xba, 0xe8, 0x87, 0x1a, 0xcc, 0xad, + 0x90, 0x86, 0x4b, 0xa7, 0x6d, 0xd5, 0xc1, 0xb7, 0xe7, 0x67, 0x56, 0x41, + 0xf7, 0x03, 0xb3, 0x09, 0x61, 0x63, 0xb5, 0xb0, 0x19, 0x7b, 0xc5, 0x91, + 0xc8, 0x96, 0x5b, 0x6a, 0x80, 0xa1, 0x53, 0x0f, 0x9a, 0x47, 0xb5, 0x9a, + 0x44, 0x53, 0xbd, 0x93, 0xe3, 0xe4, 0xce, 0x0c, 0x17, 0x11, 0x51, 0x1d, + 0xfd, 0x6c, 0x74, 0xe4, 0xec, 0x2a, 0xce, 0x57, 0x27, 0xcc, 0x83, 0x98, + 0x08, 0x32, 0x2c, 0xd5, 0x75, 0xa9, 0x27, 0xfe, 0xaa, 0x5e, 0x48, 0xc9, + 0x46, 0x9a, 0x29, 0x3f, 0xe6, 0x01, 0x4d, 0x97, 0x4a, 0x70, 0xd1, 0x5d, + 0xf8, 0xc0, 0x0b, 0x23, 0xcb, 0xbe, 0xf5, 0x70, 0x0b, 0xc2, 0xf2, 0xc0, + 0x33, 0x9c, 0xc4, 0x8b, 0x39, 0x7e, 0x3d, 0xc6, 0x23, 0x39, 0x9a, 0x98, + 0xdd, 0x02, 0x01, 0x01, +}; + +static bool TestRSA(const uint8_t *der, size_t der_len, + const uint8_t *oaep_ciphertext, + size_t oaep_ciphertext_len) { + ScopedRSA key(RSA_private_key_from_bytes(der, der_len)); + if (!key) { + return false; + } + + if (!RSA_check_key(key.get())) { + fprintf(stderr, "RSA_check_key failed\n"); + return false; + } + + uint8_t ciphertext[256]; + + size_t ciphertext_len = 0; + if (!RSA_encrypt(key.get(), &ciphertext_len, ciphertext, sizeof(ciphertext), + kPlaintext, kPlaintextLen, RSA_PKCS1_PADDING) || + ciphertext_len != RSA_size(key.get())) { + fprintf(stderr, "PKCS#1 v1.5 encryption failed!\n"); + return false; + } + + uint8_t plaintext[256]; + size_t plaintext_len = 0; + if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, ciphertext_len, RSA_PKCS1_PADDING) || + plaintext_len != kPlaintextLen || + memcmp(plaintext, kPlaintext, plaintext_len) != 0) { + fprintf(stderr, "PKCS#1 v1.5 decryption failed!\n"); + return false; + } + + ciphertext_len = 0; + if (!RSA_encrypt(key.get(), &ciphertext_len, ciphertext, sizeof(ciphertext), + kPlaintext, kPlaintextLen, RSA_PKCS1_OAEP_PADDING) || + ciphertext_len != RSA_size(key.get())) { + fprintf(stderr, "OAEP encryption failed!\n"); + return false; + } + + plaintext_len = 0; + if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, ciphertext_len, RSA_PKCS1_OAEP_PADDING) || + plaintext_len != kPlaintextLen || + memcmp(plaintext, kPlaintext, plaintext_len) != 0) { + fprintf(stderr, "OAEP decryption (encrypted data) failed!\n"); + return false; + } + + // |oaep_ciphertext| should decrypt to |kPlaintext|. + plaintext_len = 0; + if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + oaep_ciphertext, oaep_ciphertext_len, + RSA_PKCS1_OAEP_PADDING) || + plaintext_len != kPlaintextLen || + memcmp(plaintext, kPlaintext, plaintext_len) != 0) { + fprintf(stderr, "OAEP decryption (test vector data) failed!\n"); + return false; + } + + // Try decrypting corrupted ciphertexts. + memcpy(ciphertext, oaep_ciphertext, oaep_ciphertext_len); + for (size_t i = 0; i < oaep_ciphertext_len; i++) { + ciphertext[i] ^= 1; + if (RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, oaep_ciphertext_len, RSA_PKCS1_OAEP_PADDING)) { + fprintf(stderr, "Corrupt data decrypted!\n"); + return false; + } + ERR_clear_error(); + ciphertext[i] ^= 1; + } + + // Test truncated ciphertexts. + for (size_t len = 0; len < oaep_ciphertext_len; len++) { + if (RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, len, RSA_PKCS1_OAEP_PADDING)) { + fprintf(stderr, "Corrupt data decrypted!\n"); + return false; + } + ERR_clear_error(); + } + + return true; +} + +static bool TestMultiPrimeKey(int nprimes, const uint8_t *der, size_t der_size, + const uint8_t *enc, size_t enc_size) { + ScopedRSA rsa(d2i_RSAPrivateKey(nullptr, &der, der_size)); + if (!rsa) { + fprintf(stderr, "%d-prime key failed to parse.\n", nprimes); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_check_key(rsa.get())) { + fprintf(stderr, "RSA_check_key failed for %d-prime key.\n", nprimes); + ERR_print_errors_fp(stderr); + return false; + } + + uint8_t out[256]; + size_t out_len; + if (!RSA_decrypt(rsa.get(), &out_len, out, sizeof(out), enc, enc_size, + RSA_PKCS1_PADDING) || + out_len != 11 || + memcmp(out, "hello world", 11) != 0) { + fprintf(stderr, "%d-prime key failed to decrypt.\n", nprimes); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestMultiPrimeKeygen() { + static const char kMessage[] = "Hello world."; + static const size_t kBits = 1024; + uint8_t encrypted[kBits / 8], decrypted[kBits / 8]; + size_t encrypted_len, decrypted_len; + + ScopedRSA rsa(RSA_new()); + ScopedBIGNUM e(BN_new()); + if (!rsa || !e || + !BN_set_word(e.get(), RSA_F4) || + !RSA_generate_multi_prime_key(rsa.get(), kBits, 3, e.get(), nullptr) || + !RSA_check_key(rsa.get()) || + !RSA_encrypt(rsa.get(), &encrypted_len, encrypted, sizeof(encrypted), + (const uint8_t *)kMessage, sizeof(kMessage), + RSA_PKCS1_PADDING) || + !RSA_decrypt(rsa.get(), &decrypted_len, decrypted, sizeof(decrypted), + encrypted, encrypted_len, RSA_PKCS1_PADDING) || + decrypted_len != sizeof(kMessage) || + memcmp(decrypted, kMessage, sizeof(kMessage)) != 0) { + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestBadKey() { + ScopedRSA key(RSA_new()); + ScopedBIGNUM e(BN_new()); + + if (!key || !e || !BN_set_word(e.get(), RSA_F4)) { + return false; + } + + if (!RSA_generate_key_ex(key.get(), 512, e.get(), nullptr)) { + fprintf(stderr, "RSA_generate_key_ex failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!BN_add(key->p, key->p, BN_value_one())) { + fprintf(stderr, "BN error.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (RSA_check_key(key.get())) { + fprintf(stderr, "RSA_check_key passed with invalid key!\n"); + return false; + } + + ERR_clear_error(); + return true; +} + +static bool TestOnlyDGiven() { + static const char kN[] = + "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd09ac42b2662" + "1cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e5808c659"; + static const char kE[] = "010001"; + static const char kD[] = + "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea316eaeca21a" + "73ac365e58713195f2ae9849348525ca855386b6d028e437a9495a01"; + + uint8_t buf[64]; + unsigned buf_len = sizeof(buf); + ScopedRSA key(RSA_new()); + if (!key || + !BN_hex2bn(&key->n, kN) || + !BN_hex2bn(&key->e, kE) || + !BN_hex2bn(&key->d, kD) || + RSA_size(key.get()) > sizeof(buf)) { + return false; + } + + if (!RSA_check_key(key.get())) { + fprintf(stderr, "RSA_check_key failed with only n, d, and e given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + const uint8_t kDummyHash[16] = {0}; + + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len, + key.get())) { + fprintf(stderr, "RSA_sign failed with only n, d, and e given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len, + key.get())) { + fprintf(stderr, "RSA_verify failed with only n, d, and e given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + // Keys without the public exponent must continue to work when blinding is + // disabled to support Java's RSAPrivateKeySpec API. See + // https://bugs.chromium.org/p/boringssl/issues/detail?id=12. + ScopedRSA key2(RSA_new()); + if (!key2 || + !BN_hex2bn(&key2->n, kN) || + !BN_hex2bn(&key2->d, kD)) { + return false; + } + key2->flags |= RSA_FLAG_NO_BLINDING; + + if (RSA_size(key2.get()) > sizeof(buf)) { + return false; + } + + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len, + key2.get())) { + fprintf(stderr, "RSA_sign failed with only n and d given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + // Verify the signature with |key|. |key2| has no public exponent. + if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len, + key.get())) { + fprintf(stderr, + "Could not verify signature produced from key with only n and d " + "given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestRecoverCRTParams() { + ScopedBIGNUM e(BN_new()); + if (!e || !BN_set_word(e.get(), RSA_F4)) { + return false; + } + + ERR_clear_error(); + + for (unsigned i = 0; i < 1; i++) { + ScopedRSA key1(RSA_new()); + if (!key1 || + !RSA_generate_key_ex(key1.get(), 512, e.get(), nullptr)) { + fprintf(stderr, "RSA_generate_key_ex failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_check_key(key1.get())) { + fprintf(stderr, "RSA_check_key failed with original key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedRSA key2(RSA_new()); + if (!key2) { + return false; + } + key2->n = BN_dup(key1->n); + key2->e = BN_dup(key1->e); + key2->d = BN_dup(key1->d); + if (key2->n == nullptr || key2->e == nullptr || key2->d == nullptr) { + return false; + } + + if (!RSA_recover_crt_params(key2.get())) { + fprintf(stderr, "RSA_recover_crt_params failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + uint8_t buf[128]; + unsigned buf_len = sizeof(buf); + if (RSA_size(key2.get()) > buf_len) { + return false; + } + + if (!RSA_check_key(key2.get())) { + fprintf(stderr, "RSA_check_key failed with recovered key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + const uint8_t kDummyHash[16] = {0}; + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len, + key2.get())) { + fprintf(stderr, "RSA_sign failed with recovered key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len, + key2.get())) { + fprintf(stderr, "RSA_verify failed with recovered key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + } + + return true; +} + +static bool TestASN1() { + // Test that private keys may be decoded. + ScopedRSA rsa(RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1)); + if (!rsa) { + return false; + } + + // Test that the serialization round-trips. + uint8_t *der; + size_t der_len; + if (!RSA_private_key_to_bytes(&der, &der_len, rsa.get())) { + return false; + } + ScopedOpenSSLBytes delete_der(der); + if (der_len != sizeof(kKey1) - 1 || memcmp(der, kKey1, der_len) != 0) { + return false; + } + + // Test that serializing public keys works. + if (!RSA_public_key_to_bytes(&der, &der_len, rsa.get())) { + return false; + } + delete_der.reset(der); + + // Public keys may be parsed back out. + rsa.reset(RSA_public_key_from_bytes(der, der_len)); + if (!rsa || rsa->p != NULL || rsa->q != NULL) { + return false; + } + + // Serializing the result round-trips. + uint8_t *der2; + size_t der2_len; + if (!RSA_public_key_to_bytes(&der2, &der2_len, rsa.get())) { + return false; + } + ScopedOpenSSLBytes delete_der2(der2); + if (der_len != der2_len || memcmp(der, der2, der_len) != 0) { + return false; + } + + // Public keys cannot be serialized as private keys. + if (RSA_private_key_to_bytes(&der, &der_len, rsa.get())) { + OPENSSL_free(der); + return false; + } + ERR_clear_error(); + + // Public keys with negative moduli are invalid. + rsa.reset(RSA_public_key_from_bytes(kEstonianRSAKey, + sizeof(kEstonianRSAKey))); + if (rsa) { + return false; + } + ERR_clear_error(); + + // But |RSA_parse_public_key_buggy| will accept it. + CBS cbs; + CBS_init(&cbs, kEstonianRSAKey, sizeof(kEstonianRSAKey)); + rsa.reset(RSA_parse_public_key_buggy(&cbs)); + if (!rsa || CBS_len(&cbs) != 0) { + return false; + } + + return true; +} + +static bool TestBadExponent() { + ScopedRSA rsa(RSA_public_key_from_bytes(kExponent1RSAKey, + sizeof(kExponent1RSAKey))); + + if (rsa) { + fprintf(stderr, "kExponent1RSAKey parsed but should have failed.\n"); + return false; + } + + ERR_clear_error(); + return true; +} + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + if (!TestRSA(kKey1, sizeof(kKey1) - 1, kOAEPCiphertext1, + sizeof(kOAEPCiphertext1) - 1) || + !TestRSA(kKey2, sizeof(kKey2) - 1, kOAEPCiphertext2, + sizeof(kOAEPCiphertext2) - 1) || + !TestRSA(kKey3, sizeof(kKey3) - 1, kOAEPCiphertext3, + sizeof(kOAEPCiphertext3) - 1) || + !TestOnlyDGiven() || + !TestRecoverCRTParams() || + !TestBadKey() || + !TestMultiPrimeKey(2, kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1, + kTwoPrimeEncryptedMessage, + sizeof(kTwoPrimeEncryptedMessage)) || + !TestMultiPrimeKey(3, kThreePrimeKey, sizeof(kThreePrimeKey) - 1, + kThreePrimeEncryptedMessage, + sizeof(kThreePrimeEncryptedMessage)) || + !TestMultiPrimeKey(6, kSixPrimeKey, sizeof(kSixPrimeKey) - 1, + kSixPrimeEncryptedMessage, + sizeof(kSixPrimeEncryptedMessage)) || + !TestMultiPrimeKeygen() || + !TestASN1() || + !TestBadExponent()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/sha/CMakeLists.txt b/external/boringssl/crypto/sha/CMakeLists.txt new file mode 100644 index 0000000000..ecff09b82a --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/sha/asm/sha1-586.pl b/external/boringssl/crypto/sha/asm/sha1-586.pl new file mode 100644 index 0000000000..35142737ed --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-586.pl @@ -0,0 +1,1471 @@ +#!/usr/bin/env perl + +# ==================================================================== +# [Re]written by Andy Polyakov 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. +# ---------------------------------------------------------------- +# + +# 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/); } + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +$ymm = 1; + +$ymm = 0 unless ($xmm); + +$shaext=$xmm; ### set to zero if compiling for 1.0.1 + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$shaext = 0; + +&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,&DWP(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 "); + +&asm_finish(); diff --git a/external/boringssl/crypto/sha/asm/sha1-armv4-large.pl b/external/boringssl/crypto/sha/asm/sha1-armv4-large.pl new file mode 100644 index 0000000000..64e2ed6112 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-armv4-large.pl @@ -0,0 +1,701 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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. Cortex-A15 +# is even faster spending 5.6 cycles per byte outperforming integer- +# only code by factor of 2. + +# May 2014. +# +# Add ARMv8 code path performing at 2.35 cpb on Apple A7. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + 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 + +.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 +#ifdef __APPLE__ + ldr r12,[r12] +#endif + 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 " +.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 +.hidden OPENSSL_armcap_P +#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/external/boringssl/crypto/sha/asm/sha1-armv8.pl b/external/boringssl/crypto/sha/asm/sha1-armv8.pl new file mode 100644 index 0000000000..1c4fe4a21d --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-armv8.pl @@ -0,0 +1,347 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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.24 8.03 (+97%) +# Cortex-A57 2.35 7.88 (+74%) +# Denver 2.13 3.97 (+0%)(**) +# X-Gene 8.80 (+200%) +# +# (*) Software results are presented mostly for reference purposes. +# (**) Keep in mind that Denver relies on binary translation, which +# optimizes compiler output at run-time. + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +($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 + +.text + +.extern OPENSSL_armcap_P +.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 " +.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/external/boringssl/crypto/sha/asm/sha1-x86_64.pl b/external/boringssl/crypto/sha/asm/sha1-x86_64.pl new file mode 100644 index 0000000000..4895f922ae --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-x86_64.pl @@ -0,0 +1,2059 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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"; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable AVX2 code after testing by setting $avx to 2. Is it +# necessary to disable AVX2 code when SHA Extensions code is disabled? Upstream +# did not tie them together until after $shaext was added. +$avx = 1; + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$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 " +.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->RipRsp + + 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/external/boringssl/crypto/sha/asm/sha256-586.pl b/external/boringssl/crypto/sha/asm/sha256-586.pl new file mode 100644 index 0000000000..fa8f264d3d --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha256-586.pl @@ -0,0 +1,1275 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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/); } + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable AVX2 code after testing by setting $avx to 2. +$avx = 1; + +$avx = 0 unless ($xmm); + +$shaext=$xmm; ### set to zero if compiling for 1.0.1 + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$shaext = 0; + +$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 "); + +($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/external/boringssl/crypto/sha/asm/sha256-armv4.pl b/external/boringssl/crypto/sha/asm/sha256-armv4.pl new file mode 100644 index 0000000000..7e071474e1 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha256-armv4.pl @@ -0,0 +1,735 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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/. +# +# Permission to use under GPL terms is granted. +# ==================================================================== + +# 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. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + 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) +# ifndef __ARMEB__ + rev $t1,$t1 +# endif +#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=<<___; +#ifndef __KERNEL__ +# include +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +#endif + +.text +#if __ARM_ARCH__<7 +.code 32 +#else +.syntax unified +# if defined(__thumb2__) && !defined(__APPLE__) +# define adrl adr +.thumb +# else +.code 32 +# endif +#endif + +.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 && !defined(__KERNEL__) +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lsha256_block_data_order +#endif +.align 5 + +.global sha256_block_data_order +.type sha256_block_data_order,%function +sha256_block_data_order: +.Lsha256_block_data_order: +#if __ARM_ARCH__<7 + sub r3,pc,#8 @ sha256_block_data_order +#else + adr r3,sha256_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV8_SHA256 + bne .LARMv8 + tst r12,#ARMV7_NEON + bne .LNEON +#endif + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + 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.=<<___; +#if __ARM_ARCH__>=7 + ite eq @ Thumb2 thing, sanity check in ARM +#endif + 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 + +.global sha256_block_data_order_neon +.type sha256_block_data_order_neon,%function +.align 4 +sha256_block_data_order_neon: +.LNEON: + stmdb sp!,{r4-r12,lr} + + sub $H,sp,#16*4+16 + adrl $Ktbl,K256 + bic $H,$H,#15 @ align for 128-bit stores + mov $t2,sp + mov sp,$H @ alloca + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + + 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 + it eq + 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]! + it ne + 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} + + ittte ne + movne $Xfer,sp + ldrne $t1,[sp,#0] + eorne $t2,$t2,$t2 + ldreq sp,[sp,#76] @ restore original sp + itt ne + 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 && !defined(__KERNEL__) + +# if defined(__thumb2__) && !defined(__APPLE__) +# define INST(a,b,c,d) .byte c,d|0xc,a,b +# else +# define INST(a,b,c,d) .byte a,b,c,d +# endif + +.type sha256_block_data_order_armv8,%function +.align 5 +sha256_block_data_order_armv8: +.LARMv8: + vld1.32 {$ABCD,$EFGH},[$ctx] +# ifdef __APPLE__ + sub $Ktbl,$Ktbl,#256+32 +# elif defined(__thumb2__) + adr $Ktbl,.LARMv8 + sub $Ktbl,$Ktbl,#.LARMv8-K256 +# else + adrl $Ktbl,K256 +# endif + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + +.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 + it ne + 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 " +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +#endif +___ + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +{ 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 "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + } +} + +foreach (split($/,$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/external/boringssl/crypto/sha/asm/sha512-586.pl b/external/boringssl/crypto/sha/asm/sha512-586.pl new file mode 100644 index 0000000000..2f6a202c37 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-586.pl @@ -0,0 +1,911 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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 "); + +&asm_finish(); diff --git a/external/boringssl/crypto/sha/asm/sha512-armv4.pl b/external/boringssl/crypto/sha/asm/sha512-armv4.pl new file mode 100644 index 0000000000..15d50f2817 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-armv4.pl @@ -0,0 +1,666 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov 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/. +# +# Permission to use under GPL terms is granted. +# ==================================================================== + +# 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, see http://www.openssl.org/~appro/Snapdragon-S4.html +# for further details. On side note Cortex-A15 processes one byte in +# 16 cycles. + +# 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"; +# ==================================================================== + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + 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 +#if __ARM_ARCH__>=7 + it eq @ Thumb2 thing, sanity check in ARM +#endif + 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=<<___; +#ifndef __KERNEL__ +# include +# define VFP_ABI_PUSH vstmdb sp!,{d8-d15} +# define VFP_ABI_POP vldmia sp!,{d8-d15} +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +# define VFP_ABI_PUSH +# define VFP_ABI_POP +#endif + +#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 +#if __ARM_ARCH__<7 || defined(__APPLE__) +.code 32 +#else +.syntax unified +# ifdef __thumb2__ +# define adrl adr +.thumb +# else +.code 32 +# endif +#endif + +.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 && !defined(__KERNEL__) +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lsha512_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: +.Lsha512_block_data_order: +#if __ARM_ARCH__<7 + sub r3,pc,#8 @ sha512_block_data_order +#else + adr r3,sha512_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV7_NEON + bne .LNEON +#endif + add $len,$inp,$len,lsl#7 @ len to point at the end of inp + 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.=<<___; +#if __ARM_ARCH__>=7 + ittt eq @ Thumb2 thing, sanity check in ARM +#endif + 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 +.size sha512_block_data_order,.-sha512_block_data_order +___ + +{ +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 + +.global sha512_block_data_order_neon +.type sha512_block_data_order_neon,%function +.align 4 +sha512_block_data_order_neon: +.LNEON: + dmb @ errata #451034 on early Cortex A8 + add $len,$inp,$len,lsl#7 @ len to point at the end of inp + adr $Ktbl,K512 + VFP_ABI_PUSH + 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 + + VFP_ABI_POP + ret @ bx lr +.size sha512_block_data_order_neon,.-sha512_block_data_order_neon +#endif +___ +} +$code.=<<___; +.asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +#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; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/sha/asm/sha512-armv8.pl b/external/boringssl/crypto/sha/asm/sha512-armv8.pl new file mode 100644 index 0000000000..40eb17a711 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-armv8.pl @@ -0,0 +1,436 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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.5 (+115%) 10.0 (+150%(***)) +# Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) +# Denver 2.01 10.5 (+26%) 6.70 (+8%) +# X-Gene 20.0 (+100%) 12.8 (+300%(***)) +# +# (*) 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 the gap is only 40-90%. + +$flavour=shift; +# Unlike most perlasm files, sha512-armv8.pl takes an additional argument to +# determine which hash function to emit. This differs from upstream OpenSSL so +# that the script may continue to output to stdout. +$variant=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +if ($variant eq "sha512") { + $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"; +} elsif ($variant eq "sha256") { + $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"; +} else { + die "Unknown variant: $variant"; +} + +$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 + +.text + +.extern OPENSSL_armcap_P +.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,.LK$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 .LK$BITS,%object +.LK$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 .LK$BITS,.-.LK$BITS +.align 3 +.LOPENSSL_armcap_P: + .quad OPENSSL_armcap_P-. +.asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by " +.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,.LK256 + +.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/external/boringssl/crypto/sha/asm/sha512-x86_64.pl b/external/boringssl/crypto/sha/asm/sha512-x86_64.pl new file mode 100644 index 0000000000..2bc33c65a6 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-x86_64.pl @@ -0,0 +1,2390 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov 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"; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable AVX2 code after testing by setting $avx to 2. Is it +# necessary to disable AVX2 code when SHA Extensions code is disabled? Upstream +# did not tie them together until after $shaext was added. +$avx = 1; + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$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 " +___ +} 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 " +___ +} + +###################################################################### +# 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->RipRsp + + 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->RipRbx + 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 && $shaext); + .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/external/boringssl/crypto/sha/sha1.c b/external/boringssl/crypto/sha/sha1.c new file mode 100644 index 0000000000..74e841caff --- /dev/null +++ b/external/boringssl/crypto/sha/sha1.c @@ -0,0 +1,337 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +#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->h[0] = 0x67452301UL; + sha->h[1] = 0xefcdab89UL; + sha->h[2] = 0x98badcfeUL; + sha->h[3] = 0x10325476UL; + sha->h[4] = 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_CTX SHA_CTX +#define HASH_CBLOCK 64 +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[4]; \ + 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 ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) +#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(uint32_t *state, const uint8_t *data, 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 , 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... +* */ +#define X(i) XX##i + +#if !defined(SHA1_ASM) +static void sha1_block_data_order(uint32_t *state, const uint8_t *data, + size_t num) { + register uint32_t A, B, C, D, E, T, l; + uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, + XX11, XX12, XX13, XX14, XX15; + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + E = state[4]; + + for (;;) { + (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)); + + state[0] = (state[0] + E) & 0xffffffffL; + state[1] = (state[1] + T) & 0xffffffffL; + state[2] = (state[2] + A) & 0xffffffffL; + state[3] = (state[3] + B) & 0xffffffffL; + state[4] = (state[4] + C) & 0xffffffffL; + + if (--num == 0) { + break; + } + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + E = state[4]; + } +} +#endif diff --git a/external/boringssl/crypto/sha/sha256.c b/external/boringssl/crypto/sha/sha256.c new file mode 100644 index 0000000000..58f7c42c36 --- /dev/null +++ b/external/boringssl/crypto/sha/sha256.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 + +#include + +#include + + +#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); + SHA224_Update(&ctx, data, len); + SHA224_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_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. + * + * TODO(davidben): The small |md_len| case is one of the few places a low-level + * hash 'final' function can fail. This should never happen. */ +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t 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]; \ + HOST_l2c(ll, (s)); \ + } \ + break; \ + case SHA256_DIGEST_LENGTH: \ + for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { \ + ll = (c)->h[nn]; \ + 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]; \ + 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(uint32_t *state, const uint8_t *in, size_t num); + +#include "../digest/md32_common.h" + +#ifndef SHA256_ASM +static const uint32_t 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}; + +#define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) + +/* 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(uint32_t *state, const uint8_t *data, + size_t num) { + uint32_t a, b, c, d, e, f, g, h, s0, s1, T1; + uint32_t X[16]; + int i; + + while (num--) { + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + uint32_t 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); + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + } +} + +#endif /* SHA256_ASM */ diff --git a/external/boringssl/crypto/sha/sha512.c b/external/boringssl/crypto/sha/sha512.c new file mode 100644 index 0000000000..f473046345 --- /dev/null +++ b/external/boringssl/crypto/sha/sha512.c @@ -0,0 +1,607 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +/* IMPLEMENTATION NOTES. + * + * The 32-bit hash algorithms share a common byte-order neutral collector and + * padding function implementations that operate on unaligned data, + * ../md32_common.h. This SHA-512 implementation does not. 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 a transform function that operates on *aligned* data + * the collector/padding function is simpler and easier to optimize. */ + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +#define SHA512_ASM +#endif + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(__ARM_FEATURE_UNALIGNED) +#define SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA +#endif + +int SHA384_Init(SHA512_CTX *sha) { + sha->h[0] = UINT64_C(0xcbbb9d5dc1059ed8); + sha->h[1] = UINT64_C(0x629a292a367cd507); + sha->h[2] = UINT64_C(0x9159015a3070dd17); + sha->h[3] = UINT64_C(0x152fecd8f70e5939); + sha->h[4] = UINT64_C(0x67332667ffc00b31); + sha->h[5] = UINT64_C(0x8eb44a8768581511); + sha->h[6] = UINT64_C(0xdb0c2e0d64f98fa7); + sha->h[7] = UINT64_C(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] = UINT64_C(0x6a09e667f3bcc908); + sha->h[1] = UINT64_C(0xbb67ae8584caa73b); + sha->h[2] = UINT64_C(0x3c6ef372fe94f82b); + sha->h[3] = UINT64_C(0xa54ff53a5f1d36f1); + sha->h[4] = UINT64_C(0x510e527fade682d1); + sha->h[5] = UINT64_C(0x9b05688c2b3e6c1f); + sha->h[6] = UINT64_C(0x1f83d9abfb41bd6b); + sha->h[7] = UINT64_C(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); + SHA384_Update(&ctx, data, len); + SHA384_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(uint64_t *state, const uint64_t *W, size_t num); + + +int SHA384_Final(uint8_t *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 uint8_t *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->h, (uint64_t *)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)) & UINT64_C(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->h, (uint64_t *)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->h, (uint64_t *)p, 1); + len -= sizeof(c->u); + data += sizeof(c->u); + } + } else +#endif + { + sha512_block_data_order(c->h, (uint64_t *)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(uint8_t *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->h, (uint64_t *)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->h, (uint64_t *)p, 1); + + if (md == NULL) { + /* TODO(davidben): This NULL check is absent in other low-level hash 'final' + * functions and is one of the few places one can fail. */ + 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: + /* TODO(davidben): This bad |md_len| case is one of the few places a + * low-level hash 'final' function can fail. This should never happen. */ + return 0; + } + + return 1; +} + +#ifndef SHA512_ASM +static const uint64_t K512[80] = { + UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), + UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), + UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), + UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), + UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), + UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), + UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), + UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), + UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), + UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), + UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), + UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), + UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), + UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), + UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), + UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), + UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), + UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), + UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), + UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), + UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), + UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), + UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), + UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), + UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), + UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), + UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), + UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), + UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), + UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), + UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), + UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), + UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), + UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), + UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), + UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), + UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), + UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), + UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), + UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(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 uint8_t *)(&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(uint64_t *state, const uint64_t *W, + size_t num) { + uint64_t A, E, T; + uint64_t X[9 + 80], *F; + int i; + + while (num--) { + F = X + 80; + A = state[0]; + F[1] = state[1]; + F[2] = state[2]; + F[3] = state[3]; + E = state[4]; + F[5] = state[5]; + F[6] = state[6]; + F[7] = state[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]); + } + + state[0] += A; + state[1] += F[1]; + state[2] += F[2]; + state[3] += F[3]; + state[4] += E; + state[5] += F[5]; + state[6] += F[6]; + state[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(uint64_t *state, const uint64_t *W, + size_t num) { + uint64_t a, b, c, d, e, f, g, h, s0, s1, T1; + uint64_t X[16]; + int i; + + while (num--) { + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[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); + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + + W += 16; + } +} + +#endif + +#endif /* SHA512_ASM */ diff --git a/external/boringssl/crypto/stack/CMakeLists.txt b/external/boringssl/crypto/stack/CMakeLists.txt new file mode 100644 index 0000000000..dcd8ef49e0 --- /dev/null +++ b/external/boringssl/crypto/stack/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + stack + + OBJECT + + stack.c +) diff --git a/external/boringssl/crypto/stack/make_macros.sh b/external/boringssl/crypto/stack/make_macros.sh new file mode 100644 index 0000000000..3c3691b316 --- /dev/null +++ b/external/boringssl/crypto/stack/make_macros.sh @@ -0,0 +1,114 @@ +#!/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(const _STACK*, const 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(const _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(const _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(const _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))) + +#define sk_${type}_deep_copy(sk, copy_func, free_func)\\ +((STACK_OF(${type})*) sk_deep_copy(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), CHECKED_CAST(void* (*) (void*), ${ptrtype} (*) (${ptrtype}), copy_func), CHECKED_CAST(void (*) (void*), void (*) (${ptrtype}), free_func))) + +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/external/boringssl/crypto/stack/stack.c b/external/boringssl/crypto/stack/stack.c new file mode 100644 index 0000000000..e8932217bd --- /dev/null +++ b/external/boringssl/crypto/stack/stack.c @@ -0,0 +1,386 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + +/* 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: + 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 0; + } + + 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: + sk_free(ret); + return NULL; +} + +void sk_sort(_STACK *sk) { + int (*comp_func)(const void *,const void *); + + if (sk == NULL || sk->comp == 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; +} + +_STACK *sk_deep_copy(const _STACK *sk, void *(*copy_func)(void *), + void (*free_func)(void *)) { + _STACK *ret = sk_dup(sk); + if (ret == NULL) { + return NULL; + } + + size_t i; + for (i = 0; i < ret->num; i++) { + if (ret->data[i] == NULL) { + continue; + } + ret->data[i] = copy_func(ret->data[i]); + if (ret->data[i] == NULL) { + size_t j; + for (j = 0; j < i; j++) { + if (ret->data[j] != NULL) { + free_func(ret->data[j]); + } + } + sk_free(ret); + return NULL; + } + } + + return ret; +} diff --git a/external/boringssl/crypto/test/CMakeLists.txt b/external/boringssl/crypto/test/CMakeLists.txt new file mode 100644 index 0000000000..8c75314339 --- /dev/null +++ b/external/boringssl/crypto/test/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library( + test_support + + OBJECT + + file_test.cc + malloc.cc + test_util.cc +) diff --git a/external/boringssl/crypto/test/file_test.cc b/external/boringssl/crypto/test/file_test.cc new file mode 100644 index 0000000000..d684aa09fe --- /dev/null +++ b/external/boringssl/crypto/test/file_test.cc @@ -0,0 +1,302 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "file_test.h" + +#include + +#include +#include +#include +#include +#include + +#include + + +FileTest::FileTest(const char *path) { + file_ = fopen(path, "r"); + if (file_ == nullptr) { + fprintf(stderr, "Could not open file %s: %s.\n", path, strerror(errno)); + } +} + +FileTest::~FileTest() { + if (file_ != nullptr) { + fclose(file_); + } +} + +// FindDelimiter returns a pointer to the first '=' or ':' in |str| or nullptr +// if there is none. +static const char *FindDelimiter(const char *str) { + while (*str) { + if (*str == ':' || *str == '=') { + return str; + } + str++; + } + return nullptr; +} + +// StripSpace returns a string containing up to |len| characters from |str| with +// leading and trailing whitespace removed. +static std::string StripSpace(const char *str, size_t len) { + // Remove leading space. + while (len > 0 && isspace(*str)) { + str++; + len--; + } + while (len > 0 && isspace(str[len-1])) { + len--; + } + return std::string(str, len); +} + +FileTest::ReadResult FileTest::ReadNext() { + // If the previous test had unused attributes, it is an error. + if (!unused_attributes_.empty()) { + for (const std::string &key : unused_attributes_) { + PrintLine("Unused attribute: %s", key.c_str()); + } + return kReadError; + } + + ClearTest(); + + static const size_t kBufLen = 64 + 8192*2; + std::unique_ptr buf(new char[kBufLen]); + + while (true) { + // Read the next line. + if (fgets(buf.get(), kBufLen, file_) == nullptr) { + if (feof(file_)) { + // EOF is a valid terminator for a test. + return start_line_ > 0 ? kReadSuccess : kReadEOF; + } + fprintf(stderr, "Error reading from input.\n"); + return kReadError; + } + + line_++; + size_t len = strlen(buf.get()); + // Check for truncation. + if (len > 0 && buf[len - 1] != '\n' && !feof(file_)) { + fprintf(stderr, "Line %u too long.\n", line_); + return kReadError; + } + + if (buf[0] == '\n' || buf[0] == '\0') { + // Empty lines delimit tests. + if (start_line_ > 0) { + return kReadSuccess; + } + } else if (buf[0] != '#') { // Comment lines are ignored. + // Parse the line as an attribute. + const char *delimiter = FindDelimiter(buf.get()); + if (delimiter == nullptr) { + fprintf(stderr, "Line %u: Could not parse attribute.\n", line_); + return kReadError; + } + std::string key = StripSpace(buf.get(), delimiter - buf.get()); + std::string value = StripSpace(delimiter + 1, + buf.get() + len - delimiter - 1); + + unused_attributes_.insert(key); + attributes_[key] = value; + if (start_line_ == 0) { + // This is the start of a test. + type_ = key; + parameter_ = value; + start_line_ = line_; + } + } + } +} + +void FileTest::PrintLine(const char *format, ...) { + va_list args; + va_start(args, format); + + fprintf(stderr, "Line %u: ", start_line_); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + + va_end(args); +} + +const std::string &FileTest::GetType() { + OnKeyUsed(type_); + return type_; +} + +const std::string &FileTest::GetParameter() { + OnKeyUsed(type_); + return parameter_; +} + +bool FileTest::HasAttribute(const std::string &key) { + OnKeyUsed(key); + return attributes_.count(key) > 0; +} + +bool FileTest::GetAttribute(std::string *out_value, const std::string &key) { + OnKeyUsed(key); + auto iter = attributes_.find(key); + if (iter == attributes_.end()) { + PrintLine("Missing attribute '%s'.", key.c_str()); + return false; + } + *out_value = iter->second; + return true; +} + +const std::string &FileTest::GetAttributeOrDie(const std::string &key) { + if (!HasAttribute(key)) { + abort(); + } + return attributes_[key]; +} + +static bool FromHexDigit(uint8_t *out, char c) { + if ('0' <= c && c <= '9') { + *out = c - '0'; + return true; + } + if ('a' <= c && c <= 'f') { + *out = c - 'a' + 10; + return true; + } + if ('A' <= c && c <= 'F') { + *out = c - 'A' + 10; + return true; + } + return false; +} + +bool FileTest::GetBytes(std::vector *out, const std::string &key) { + std::string value; + if (!GetAttribute(&value, key)) { + return false; + } + + if (value.size() >= 2 && value[0] == '"' && value[value.size() - 1] == '"') { + out->assign(value.begin() + 1, value.end() - 1); + return true; + } + + if (value.size() % 2 != 0) { + PrintLine("Error decoding value: %s", value.c_str()); + return false; + } + out->clear(); + out->reserve(value.size() / 2); + for (size_t i = 0; i < value.size(); i += 2) { + uint8_t hi, lo; + if (!FromHexDigit(&hi, value[i]) || !FromHexDigit(&lo, value[i+1])) { + PrintLine("Error decoding value: %s", value.c_str()); + return false; + } + out->push_back((hi << 4) | lo); + } + return true; +} + +static std::string EncodeHex(const uint8_t *in, size_t in_len) { + static const char kHexDigits[] = "0123456789abcdef"; + std::string ret; + ret.reserve(in_len * 2); + for (size_t i = 0; i < in_len; i++) { + ret += kHexDigits[in[i] >> 4]; + ret += kHexDigits[in[i] & 0xf]; + } + return ret; +} + +bool FileTest::ExpectBytesEqual(const uint8_t *expected, size_t expected_len, + const uint8_t *actual, size_t actual_len) { + if (expected_len == actual_len && + memcmp(expected, actual, expected_len) == 0) { + return true; + } + + std::string expected_hex = EncodeHex(expected, expected_len); + std::string actual_hex = EncodeHex(actual, actual_len); + PrintLine("Expected: %s", expected_hex.c_str()); + PrintLine("Actual: %s", actual_hex.c_str()); + return false; +} + +void FileTest::ClearTest() { + start_line_ = 0; + type_.clear(); + parameter_.clear(); + attributes_.clear(); + unused_attributes_.clear(); +} + +void FileTest::OnKeyUsed(const std::string &key) { + unused_attributes_.erase(key); +} + +int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg, + const char *path) { + FileTest t(path); + if (!t.is_open()) { + return 1; + } + + bool failed = false; + while (true) { + FileTest::ReadResult ret = t.ReadNext(); + if (ret == FileTest::kReadError) { + return 1; + } else if (ret == FileTest::kReadEOF) { + break; + } + + bool result = run_test(&t, arg); + if (t.HasAttribute("Error")) { + if (result) { + t.PrintLine("Operation unexpectedly succeeded."); + failed = true; + continue; + } + uint32_t err = ERR_peek_error(); + if (ERR_reason_error_string(err) != t.GetAttributeOrDie("Error")) { + t.PrintLine("Unexpected error; wanted '%s', got '%s'.", + t.GetAttributeOrDie("Error").c_str(), + ERR_reason_error_string(err)); + failed = true; + ERR_clear_error(); + continue; + } + ERR_clear_error(); + } else if (!result) { + // In case the test itself doesn't print output, print something so the + // line number is reported. + t.PrintLine("Test failed"); + ERR_print_errors_fp(stderr); + failed = true; + continue; + } + } + + if (failed) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/test/file_test.h b/external/boringssl/crypto/test/file_test.h new file mode 100644 index 0000000000..a8591277d5 --- /dev/null +++ b/external/boringssl/crypto/test/file_test.h @@ -0,0 +1,157 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H +#define OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H + +#include + +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(push)) +OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) + +#include +#include +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +// File-based test framework. +// +// This module provides a file-based test framework. The file format is based on +// that of OpenSSL upstream's evp_test and BoringSSL's aead_test. Each input +// file is a sequence of attributes and blank lines. +// +// Each attribute has the form: +// +// Name = Value +// +// Either '=' or ':' may be used to delimit the name from the value. Both the +// name and value have leading and trailing spaces stripped. +// +// Lines beginning with # are ignored. +// +// A test is a sequence of one or more attributes followed by a blank line. +// Blank lines are otherwise ignored. For tests that process multiple kinds of +// test cases, the first attribute is parsed out as the test's type and +// parameter. Otherwise, attributes are unordered. The first attribute is also +// included in the set of attributes, so tests which do not dispatch may ignore +// this mechanism. +// +// Functions in this module freely output to |stderr| on failure. Tests should +// also do so, and it is recommended they include the corresponding test's line +// number in any output. |PrintLine| does this automatically. +// +// Each attribute in a test must be consumed. When a test completes, if any +// attributes haven't been processed, the framework reports an error. + + +class FileTest { + public: + explicit FileTest(const char *path); + ~FileTest(); + + // is_open returns true if the file was successfully opened. + bool is_open() const { return file_ != nullptr; } + + enum ReadResult { + kReadSuccess, + kReadEOF, + kReadError, + }; + + // ReadNext reads the next test from the file. It returns |kReadSuccess| if + // successfully reading a test and |kReadEOF| at the end of the file. On + // error or if the previous test had unconsumed attributes, it returns + // |kReadError|. + ReadResult ReadNext(); + + // PrintLine is a variant of printf which prepends the line number and appends + // a trailing newline. + void PrintLine(const char *format, ...) OPENSSL_PRINTF_FORMAT_FUNC(2, 3); + + unsigned start_line() const { return start_line_; } + + // GetType returns the name of the first attribute of the current test. + const std::string &GetType(); + // GetParameter returns the value of the first attribute of the current test. + const std::string &GetParameter(); + + // HasAttribute returns true if the current test has an attribute named |key|. + bool HasAttribute(const std::string &key); + + // GetAttribute looks up the attribute with key |key|. It sets |*out_value| to + // the value and returns true if it exists and returns false with an error to + // |stderr| otherwise. + bool GetAttribute(std::string *out_value, const std::string &key); + + // GetAttributeOrDie looks up the attribute with key |key| and aborts if it is + // missing. It should only be used after a |HasAttribute| call. + const std::string &GetAttributeOrDie(const std::string &key); + + // GetBytes looks up the attribute with key |key| and decodes it as a byte + // string. On success, it writes the result to |*out| and returns + // true. Otherwise it returns false with an error to |stderr|. The value may + // be either a hexadecimal string or a quoted ASCII string. It returns true on + // success and returns false with an error to |stderr| on failure. + bool GetBytes(std::vector *out, const std::string &key); + + // ExpectBytesEqual returns true if |expected| and |actual| are equal. + // Otherwise, it returns false and prints a message to |stderr|. + bool ExpectBytesEqual(const uint8_t *expected, size_t expected_len, + const uint8_t *actual, size_t actual_len); + + private: + void ClearTest(); + void OnKeyUsed(const std::string &key); + + FILE *file_ = nullptr; + // line_ is the number of lines read. + unsigned line_ = 0; + + // start_line_ is the line number of the first attribute of the test. + unsigned start_line_ = 0; + // type_ is the name of the first attribute of the test. + std::string type_; + // parameter_ is the value of the first attribute. + std::string parameter_; + // attributes_ contains all attributes in the test, including the first. + std::map attributes_; + + // unused_attributes_ is the set of attributes that have been queried. + std::set unused_attributes_; + + FileTest(const FileTest&) = delete; + FileTest &operator=(const FileTest&) = delete; +}; + +// FileTestMain runs a file-based test out of |path| and returns an exit code +// suitable to return out of |main|. |run_test| should return true on pass and +// false on failure. FileTestMain also implements common handling of the 'Error' +// attribute. A test with that attribute is expected to fail. The value of the +// attribute is the reason string of the expected OpenSSL error code. +// +// Tests are guaranteed to run serially and may affect global state if need be. +// It is legal to use "tests" which, for example, import a private key into a +// list of keys. This may be used to initialize a shared set of keys for many +// tests. However, if one test fails, the framework will continue to run +// subsequent tests. +int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg, + const char *path); + + +#endif /* OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H */ diff --git a/external/boringssl/crypto/test/malloc.cc b/external/boringssl/crypto/test/malloc.cc new file mode 100644 index 0000000000..898f2a7c95 --- /dev/null +++ b/external/boringssl/crypto/test/malloc.cc @@ -0,0 +1,150 @@ +/* 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 + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) || __has_feature(memory_sanitizer) +#define OPENSSL_ASAN +#endif +#endif + +#if defined(__GLIBC__) && !defined(__UCLIBC__) +#define OPENSSL_GLIBC +#endif + +// 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. It also +// requires glibc. It's also disabled on ASan builds as this interferes with +// ASan's malloc interceptor. +// +// TODO(davidben): See if this and ASan's and MSan's interceptors can be made to +// coexist. +#if defined(__linux__) && defined(OPENSSL_GLIBC) && !defined(OPENSSL_ARM) && \ + !defined(OPENSSL_AARCH64) && !defined(OPENSSL_ASAN) + +#include +#include +#include +#include +#include +#include + +#include + + +/* 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_BREAK_ON_FAIL is also defined then the allocation + * will signal SIGTRAP 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, break_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); + } + } + break_on_fail = (NULL != getenv("MALLOC_BREAK_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 && break_on_fail) { + raise(SIGTRAP); + } + return should_fail; +} + +extern "C" { + +void *malloc(size_t size) { + if (should_fail_allocation()) { + errno = ENOMEM; + return NULL; + } + + return __libc_malloc(size); +} + +void *calloc(size_t num_elems, size_t size) { + if (should_fail_allocation()) { + errno = ENOMEM; + return NULL; + } + + return __libc_calloc(num_elems, size); +} + +void *realloc(void *ptr, size_t size) { + if (should_fail_allocation()) { + errno = ENOMEM; + return NULL; + } + + return __libc_realloc(ptr, size); +} + +} // extern "C" + +#endif /* defined(linux) && GLIBC && !ARM && !AARCH64 && !ASAN */ diff --git a/external/boringssl/crypto/test/scoped_types.h b/external/boringssl/crypto/test/scoped_types.h new file mode 100644 index 0000000000..2a2c371364 --- /dev/null +++ b/external/boringssl/crypto/test/scoped_types.h @@ -0,0 +1,145 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H +#define OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +template +struct OpenSSLDeleter { + void operator()(T *obj) { + func(obj); + } +}; + +template +struct OpenSSLStackDeleter { + void operator()(StackType *obj) { + sk_pop_free(reinterpret_cast<_STACK*>(obj), + reinterpret_cast(func)); + } +}; + +template +struct OpenSSLFree { + void operator()(T *buf) { + OPENSSL_free(buf); + } +}; + +struct FileCloser { + void operator()(FILE *file) { + fclose(file); + } +}; + +template +using ScopedOpenSSLType = std::unique_ptr>; + +template +using ScopedOpenSSLStack = + std::unique_ptr>; + +template +class ScopedOpenSSLContext { + public: + ScopedOpenSSLContext() { + init_func(&ctx_); + } + ~ScopedOpenSSLContext() { + cleanup_func(&ctx_); + } + + T *get() { return &ctx_; } + const T *get() const { return &ctx_; } + + void Reset() { + cleanup_func(&ctx_); + init_func(&ctx_); + } + + private: + T ctx_; +}; + +using ScopedASN1_TYPE = ScopedOpenSSLType; +using ScopedBIO = ScopedOpenSSLType; +using ScopedBIGNUM = ScopedOpenSSLType; +using ScopedBN_CTX = ScopedOpenSSLType; +using ScopedBN_MONT_CTX = ScopedOpenSSLType; +using ScopedCMAC_CTX = ScopedOpenSSLType; +using ScopedDH = ScopedOpenSSLType; +using ScopedECDSA_SIG = ScopedOpenSSLType; +using ScopedEC_GROUP = ScopedOpenSSLType; +using ScopedEC_KEY = ScopedOpenSSLType; +using ScopedEC_POINT = ScopedOpenSSLType; +using ScopedEVP_PKEY = ScopedOpenSSLType; +using ScopedEVP_PKEY_CTX = ScopedOpenSSLType; +using ScopedNEWHOPE_POLY = ScopedOpenSSLType; +using ScopedPKCS8_PRIV_KEY_INFO = ScopedOpenSSLType; +using ScopedPKCS12 = ScopedOpenSSLType; +using ScopedSPAKE2_CTX = ScopedOpenSSLType; +using ScopedRSA = ScopedOpenSSLType; +using ScopedX509 = ScopedOpenSSLType; +using ScopedX509_ALGOR = ScopedOpenSSLType; +using ScopedX509_SIG = ScopedOpenSSLType; +using ScopedX509_STORE_CTX = ScopedOpenSSLType; + +using ScopedX509Stack = ScopedOpenSSLStack; + +using ScopedCBB = ScopedOpenSSLContext; +using ScopedEVP_AEAD_CTX = ScopedOpenSSLContext; +using ScopedEVP_CIPHER_CTX = ScopedOpenSSLContext; +using ScopedEVP_MD_CTX = ScopedOpenSSLContext; +using ScopedHMAC_CTX = ScopedOpenSSLContext; + +using ScopedOpenSSLBytes = std::unique_ptr>; +using ScopedOpenSSLString = std::unique_ptr>; + +using ScopedFILE = std::unique_ptr; + +#endif // OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H diff --git a/external/boringssl/crypto/test/test_util.cc b/external/boringssl/crypto/test/test_util.cc new file mode 100644 index 0000000000..8021aaa864 --- /dev/null +++ b/external/boringssl/crypto/test/test_util.cc @@ -0,0 +1,30 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include "test_util.h" + + +void hexdump(FILE *fp, const char *msg, const void *in, size_t len) { + const uint8_t *data = reinterpret_cast(in); + size_t i; + + fputs(msg, fp); + for (i = 0; i < len; i++) { + fprintf(fp, "%02x", data[i]); + } + fputs("\n", fp); +} diff --git a/external/boringssl/crypto/test/test_util.h b/external/boringssl/crypto/test/test_util.h new file mode 100644 index 0000000000..972e206517 --- /dev/null +++ b/external/boringssl/crypto/test/test_util.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H +#define OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* hexdump writes |msg| to |fp| followed by the hex encoding of |len| bytes + * from |in|. */ +void hexdump(FILE *fp, const char *msg, const void *in, size_t len); + + +#if defined(__cplusplus) +} +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H */ diff --git a/external/boringssl/crypto/thread.c b/external/boringssl/crypto/thread.c new file mode 100644 index 0000000000..373f8dbca4 --- /dev/null +++ b/external/boringssl/crypto/thread.c @@ -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.] */ + +#include + +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include + + +int CRYPTO_num_locks(void) { return 1; } + +void CRYPTO_set_locking_callback(void (*func)(int mode, int lock_num, + const char *file, int line)) {} + +void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num, + const char *file, int line) { + return NULL; +} + +void CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int lock_num, + const char *file, int line)) {} + +const char *CRYPTO_get_lock_name(int lock_num) { + return "No old-style OpenSSL locks anymore"; +} + +int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) { return 1; } + +void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) {} + +void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) {} + +void CRYPTO_THREADID_current(CRYPTO_THREADID *id) {} + +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)) {} + +struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))( + const char *file, int line) { + return NULL; +} + +void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, + struct CRYPTO_dynlock_value *l, + const char *file, int line) { + return NULL; +} + +void (*CRYPTO_get_dynlock_destroy_callback(void))( + struct CRYPTO_dynlock_value *l, const char *file, int line) { + return NULL; +} diff --git a/external/boringssl/crypto/thread_none.c b/external/boringssl/crypto/thread_none.c new file mode 100644 index 0000000000..85768b4bf6 --- /dev/null +++ b/external/boringssl/crypto/thread_none.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#if defined(OPENSSL_NO_THREADS) + +void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { + if (*once) { + return; + } + *once = 1; + init(); +} + +static void *g_thread_locals[NUM_OPENSSL_THREAD_LOCALS]; + +void *CRYPTO_get_thread_local(thread_local_data_t index) { + return g_thread_locals[index]; +} + +int CRYPTO_set_thread_local(thread_local_data_t index, void *value, + thread_local_destructor_t destructor) { + g_thread_locals[index] = value; + return 1; +} + +#endif /* OPENSSL_NO_THREADS */ diff --git a/external/boringssl/crypto/thread_pthread.c b/external/boringssl/crypto/thread_pthread.c new file mode 100644 index 0000000000..2baa2b4dd4 --- /dev/null +++ b/external/boringssl/crypto/thread_pthread.c @@ -0,0 +1,176 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS) + +#include +#include +#include + +#include +#include + + +OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(pthread_rwlock_t), + CRYPTO_MUTEX_too_small); + +void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_init((pthread_rwlock_t *) lock, NULL) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_rdlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_wrlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) { + pthread_rwlock_destroy((pthread_rwlock_t *) lock); +} + +void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_rdlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_wrlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_unlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_unlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { + if (pthread_once(once, init) != 0) { + abort(); + } +} + +static pthread_mutex_t g_destructors_lock = PTHREAD_MUTEX_INITIALIZER; +static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS]; + +static void thread_local_destructor(void *arg) { + if (arg == NULL) { + return; + } + + thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS]; + if (pthread_mutex_lock(&g_destructors_lock) != 0) { + return; + } + memcpy(destructors, g_destructors, sizeof(destructors)); + pthread_mutex_unlock(&g_destructors_lock); + + unsigned i; + void **pointers = arg; + for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) { + if (destructors[i] != NULL) { + destructors[i](pointers[i]); + } + } + + OPENSSL_free(pointers); +} + +static pthread_once_t g_thread_local_init_once = PTHREAD_ONCE_INIT; +static pthread_key_t g_thread_local_key; +static int g_thread_local_failed = 0; + +static void thread_local_init(void) { + g_thread_local_failed = + pthread_key_create(&g_thread_local_key, thread_local_destructor) != 0; +} + +void *CRYPTO_get_thread_local(thread_local_data_t index) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + return NULL; + } + + void **pointers = pthread_getspecific(g_thread_local_key); + if (pointers == NULL) { + return NULL; + } + return pointers[index]; +} + +int CRYPTO_set_thread_local(thread_local_data_t index, void *value, + thread_local_destructor_t destructor) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + destructor(value); + return 0; + } + + void **pointers = pthread_getspecific(g_thread_local_key); + if (pointers == NULL) { + pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (pointers == NULL) { + destructor(value); + return 0; + } + memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (pthread_setspecific(g_thread_local_key, pointers) != 0) { + OPENSSL_free(pointers); + destructor(value); + return 0; + } + } + + if (pthread_mutex_lock(&g_destructors_lock) != 0) { + destructor(value); + return 0; + } + g_destructors[index] = destructor; + pthread_mutex_unlock(&g_destructors_lock); + + pointers[index] = value; + return 1; +} + +#endif /* !OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */ diff --git a/external/boringssl/crypto/thread_test.c b/external/boringssl/crypto/thread_test.c new file mode 100644 index 0000000000..12ca2ec026 --- /dev/null +++ b/external/boringssl/crypto/thread_test.c @@ -0,0 +1,217 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#include + + +#if !defined(OPENSSL_NO_THREADS) + +#if defined(OPENSSL_WINDOWS) + +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +typedef HANDLE thread_t; + +static DWORD WINAPI thread_run(LPVOID arg) { + void (*thread_func)(void); + /* VC really doesn't like casting between data and function pointers. */ + memcpy(&thread_func, &arg, sizeof(thread_func)); + thread_func(); + return 0; +} + +static int run_thread(thread_t *out_thread, void (*thread_func)(void)) { + void *arg; + /* VC really doesn't like casting between data and function pointers. */ + memcpy(&arg, &thread_func, sizeof(arg)); + + *out_thread = CreateThread(NULL /* security attributes */, + 0 /* default stack size */, thread_run, arg, + 0 /* run immediately */, NULL /* ignore id */); + return *out_thread != NULL; +} + +static int wait_for_thread(thread_t thread) { + return WaitForSingleObject(thread, INFINITE) == 0; +} + +#else + +#include +#include +#include + +typedef pthread_t thread_t; + +static void *thread_run(void *arg) { + void (*thread_func)(void) = arg; + thread_func(); + return NULL; +} + +static int run_thread(thread_t *out_thread, void (*thread_func)(void)) { + return pthread_create(out_thread, NULL /* default attributes */, thread_run, + thread_func) == 0; +} + +static int wait_for_thread(thread_t thread) { + return pthread_join(thread, NULL) == 0; +} + +#endif /* OPENSSL_WINDOWS */ + +static unsigned g_once_init_called = 0; + +static void once_init(void) { + g_once_init_called++; + + /* Sleep briefly so one |call_once_thread| instance will call |CRYPTO_once| + * while the other is running this function. */ +#if defined(OPENSSL_WINDOWS) + Sleep(1 /* milliseconds */); +#else + struct timespec req; + memset(&req, 0, sizeof(req)); + req.tv_nsec = 1000000; + nanosleep(&req, NULL); +#endif +} + +static CRYPTO_once_t g_test_once = CRYPTO_ONCE_INIT; + +static void call_once_thread(void) { + CRYPTO_once(&g_test_once, once_init); +} + +static int test_once(void) { + if (g_once_init_called != 0) { + fprintf(stderr, "g_once_init_called was non-zero at start.\n"); + return 0; + } + + thread_t thread1, thread2; + if (!run_thread(&thread1, call_once_thread) || + !run_thread(&thread2, call_once_thread) || + !wait_for_thread(thread1) || + !wait_for_thread(thread2)) { + fprintf(stderr, "thread failed.\n"); + return 0; + } + + CRYPTO_once(&g_test_once, once_init); + + if (g_once_init_called != 1) { + fprintf(stderr, "Expected init function to be called once, but found %u.\n", + g_once_init_called); + return 0; + } + + return 1; +} + + +static int g_test_thread_ok = 0; +static unsigned g_destructor_called_count = 0; + +static void thread_local_destructor(void *arg) { + if (arg == NULL) { + return; + } + + unsigned *count = arg; + (*count)++; +} + +static void thread_local_test_thread(void) { + void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST); + if (ptr != NULL) { + return; + } + + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_TEST, + &g_destructor_called_count, + thread_local_destructor)) { + return; + } + + if (CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST) != + &g_destructor_called_count) { + return; + } + + g_test_thread_ok = 1; +} + +static void thread_local_test2_thread(void) {} + +static int test_thread_local(void) { + void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST); + if (ptr != NULL) { + fprintf(stderr, "Thread-local data was non-NULL at start.\n"); + } + + thread_t thread; + if (!run_thread(&thread, thread_local_test_thread) || + !wait_for_thread(thread)) { + fprintf(stderr, "thread failed.\n"); + return 0; + } + + if (!g_test_thread_ok) { + fprintf(stderr, "Thread-local data didn't work in thread.\n"); + return 0; + } + + if (g_destructor_called_count != 1) { + fprintf(stderr, + "Destructor should have been called once, but actually called %u " + "times.\n", + g_destructor_called_count); + return 0; + } + + /* thread_local_test2_thread doesn't do anything, but it tests that the + * thread destructor function works even if thread-local storage wasn't used + * for a thread. */ + if (!run_thread(&thread, thread_local_test2_thread) || + !wait_for_thread(thread)) { + fprintf(stderr, "thread failed.\n"); + return 0; + } + + return 1; +} + +int main(int argc, char **argv) { + if (!test_once() || + !test_thread_local()) { + return 1; + } + + printf("PASS\n"); + return 0; +} + +#else /* OPENSSL_NO_THREADS */ + +int main(int argc, char **argv) { + printf("PASS\n"); + return 0; +} + +#endif diff --git a/external/boringssl/crypto/thread_win.c b/external/boringssl/crypto/thread_win.c new file mode 100644 index 0000000000..c7a90f7e72 --- /dev/null +++ b/external/boringssl/crypto/thread_win.c @@ -0,0 +1,237 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#if defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS) + +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#include +#include + +#include +#include + + +OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(SRWLOCK), + CRYPTO_MUTEX_too_small); + +static BOOL CALLBACK call_once_init(INIT_ONCE *once, void *arg, void **out) { + void (**init)(void) = (void (**)(void))arg; + (**init)(); + return TRUE; +} + +void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { + if (!InitOnceExecuteOnce(once, call_once_init, &init, NULL)) { + abort(); + } +} + +void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) { + InitializeSRWLock((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) { + AcquireSRWLockShared((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) { + AcquireSRWLockExclusive((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) { + ReleaseSRWLockShared((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) { + ReleaseSRWLockExclusive((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) { + /* SRWLOCKs require no cleanup. */ +} + +void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) { + AcquireSRWLockShared(&lock->lock); +} + +void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) { + AcquireSRWLockExclusive(&lock->lock); +} + +void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) { + ReleaseSRWLockShared(&lock->lock); +} + +void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) { + ReleaseSRWLockExclusive(&lock->lock); +} + +static CRITICAL_SECTION g_destructors_lock; +static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS]; + +static CRYPTO_once_t g_thread_local_init_once = CRYPTO_ONCE_INIT; +static DWORD g_thread_local_key; +static int g_thread_local_failed; + +static void thread_local_init(void) { + if (!InitializeCriticalSectionAndSpinCount(&g_destructors_lock, 0x400)) { + g_thread_local_failed = 1; + return; + } + g_thread_local_key = TlsAlloc(); + g_thread_local_failed = (g_thread_local_key == TLS_OUT_OF_INDEXES); +} + +static void NTAPI thread_local_destructor(PVOID module, DWORD reason, + PVOID reserved) { + /* Only free memory on |DLL_THREAD_DETACH|, not |DLL_PROCESS_DETACH|. In + * VS2015's debug runtime, the C runtime has been unloaded by the time + * |DLL_PROCESS_DETACH| runs. See https://crbug.com/575795. This is consistent + * with |pthread_key_create| which does not call destructors on process exit, + * only thread exit. */ + if (reason != DLL_THREAD_DETACH) { + return; + } + + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + return; + } + + void **pointers = (void**) TlsGetValue(g_thread_local_key); + if (pointers == NULL) { + return; + } + + thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS]; + + EnterCriticalSection(&g_destructors_lock); + memcpy(destructors, g_destructors, sizeof(destructors)); + LeaveCriticalSection(&g_destructors_lock); + + unsigned i; + for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) { + if (destructors[i] != NULL) { + destructors[i](pointers[i]); + } + } + + OPENSSL_free(pointers); +} + +/* Thread Termination Callbacks. + * + * Windows doesn't support a per-thread destructor with its TLS primitives. + * So, we build it manually by inserting a function to be called on each + * thread's exit. This magic is from http://www.codeproject.com/threads/tls.asp + * and it works for VC++ 7.0 and later. + * + * Force a reference to _tls_used to make the linker create the TLS directory + * if it's not already there. (E.g. if __declspec(thread) is not used). Force + * a reference to p_thread_callback_boringssl to prevent whole program + * optimization from discarding the variable. */ +#ifdef _WIN64 +#pragma comment(linker, "/INCLUDE:_tls_used") +#pragma comment(linker, "/INCLUDE:p_thread_callback_boringssl") +#else +#pragma comment(linker, "/INCLUDE:__tls_used") +#pragma comment(linker, "/INCLUDE:_p_thread_callback_boringssl") +#endif + +/* .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are + * called automatically by the OS loader code (not the CRT) when the module is + * loaded and on thread creation. They are NOT called if the module has been + * loaded by a LoadLibrary() call. It must have implicitly been loaded at + * process startup. + * + * By implicitly loaded, I mean that it is directly referenced by the main EXE + * or by one of its dependent DLLs. Delay-loaded DLL doesn't count as being + * implicitly loaded. + * + * See VC\crt\src\tlssup.c for reference. */ + +/* The linker must not discard p_thread_callback_boringssl. (We force a reference + * to this variable with a linker /INCLUDE:symbol pragma to ensure that.) If + * this variable is discarded, the OnThreadExit function will never be + * called. */ +#ifdef _WIN64 + +/* .CRT section is merged with .rdata on x64 so it must be constant data. */ +#pragma const_seg(".CRT$XLC") +/* When defining a const variable, it must have external linkage to be sure the + * linker doesn't discard it. */ +extern const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl; +const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor; +/* Reset the default section. */ +#pragma const_seg() + +#else + +#pragma data_seg(".CRT$XLC") +PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor; +/* Reset the default section. */ +#pragma data_seg() + +#endif /* _WIN64 */ + +void *CRYPTO_get_thread_local(thread_local_data_t index) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + return NULL; + } + + void **pointers = TlsGetValue(g_thread_local_key); + if (pointers == NULL) { + return NULL; + } + return pointers[index]; +} + +int CRYPTO_set_thread_local(thread_local_data_t index, void *value, + thread_local_destructor_t destructor) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + destructor(value); + return 0; + } + + void **pointers = TlsGetValue(g_thread_local_key); + if (pointers == NULL) { + pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (pointers == NULL) { + destructor(value); + return 0; + } + memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (TlsSetValue(g_thread_local_key, pointers) == 0) { + OPENSSL_free(pointers); + destructor(value); + return 0; + } + } + + EnterCriticalSection(&g_destructors_lock); + g_destructors[index] = destructor; + LeaveCriticalSection(&g_destructors_lock); + + pointers[index] = value; + return 1; +} + +#endif /* OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */ diff --git a/external/boringssl/crypto/time_support.c b/external/boringssl/crypto/time_support.c new file mode 100644 index 0000000000..ae0f49635d --- /dev/null +++ b/external/boringssl/crypto/time_support.c @@ -0,0 +1,206 @@ +/* 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 + +#include + + +#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/external/boringssl/crypto/x509/CMakeLists.txt b/external/boringssl/crypto/x509/CMakeLists.txt new file mode 100644 index 0000000000..bc86786072 --- /dev/null +++ b/external/boringssl/crypto/x509/CMakeLists.txt @@ -0,0 +1,81 @@ +include_directories(../../include) + +add_library( + x509 + + OBJECT + + a_digest.c + a_sign.c + a_strex.c + a_verify.c + algorithm.c + asn1_gen.c + by_dir.c + by_file.c + i2d_pr.c + pkcs7.c + rsa_pss.c + t_crl.c + t_req.c + t_x509.c + t_x509a.c + x509.c + x509_att.c + x509_cmp.c + x509_d2.c + x509_def.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 +) + +if(ENABLE_TESTS) +add_executable( + pkcs7_test + + pkcs7_test.c + + $ +) + +add_executable( + x509_test + + x509_test.cc + + $ +) + +target_link_libraries(pkcs7_test crypto) +target_link_libraries(x509_test crypto) +add_dependencies(all_tests pkcs7_test x509_test) +endif() diff --git a/external/boringssl/crypto/x509/a_digest.c b/external/boringssl/crypto/x509/a_digest.c new file mode 100644 index 0000000000..b88d6ac79c --- /dev/null +++ b/external/boringssl/crypto/x509/a_digest.c @@ -0,0 +1,96 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include + +int 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, 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/external/boringssl/crypto/x509/a_sign.c b/external/boringssl/crypto/x509/a_sign.c new file mode 100644 index 0000000000..13a3ac25e8 --- /dev/null +++ b/external/boringssl/crypto/x509/a_sign.c @@ -0,0 +1,135 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include + +#include "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 && !x509_digest_sign_algorithm(ctx, algor1)) { + goto err; + } + if (algor2 && !x509_digest_sign_algorithm(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, 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, 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/external/boringssl/crypto/x509/a_strex.c b/external/boringssl/crypto/x509/a_strex.c new file mode 100644 index 0000000000..aa2501a48f --- /dev/null +++ b/external/boringssl/crypto/x509/a_strex.c @@ -0,0 +1,633 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + +#include "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, "es, io_ch, NULL); + if (len < 0) + return -1; + outlen += len; + if (quotes) + outlen += 2; + if (!arg) + return outlen; + if (quotes && !io_ch(arg, "\"", 1)) + return -1; + if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0) + return -1; + if (quotes && !io_ch(arg, "\"", 1)) + return -1; + return outlen; +} + +/* Used for line indenting: print 'indent' spaces */ + +static int do_indent(char_io *io_ch, void *arg, int indent) +{ + int i; + for (i = 0; i < indent; i++) + if (!io_ch(arg, " ", 1)) + return 0; + return 1; +} + +#define FN_WIDTH_LN 25 +#define FN_WIDTH_SN 10 + +static int do_name_ex(char_io *io_ch, void *arg, 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/external/boringssl/crypto/x509/a_verify.c b/external/boringssl/crypto/x509/a_verify.c new file mode 100644 index 0000000000..5a9adb651f --- /dev/null +++ b/external/boringssl/crypto/x509/a_verify.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.] */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "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, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT); + return 0; + } + + EVP_MD_CTX_init(&ctx); + + if (!x509_digest_verify_init(&ctx, a, pkey)) { + goto err; + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + + if (buf_in == NULL) { + OPENSSL_PUT_ERROR(X509, 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, 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, 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/external/boringssl/crypto/x509/algorithm.c b/external/boringssl/crypto/x509/algorithm.c new file mode 100644 index 0000000000..78ae882b80 --- /dev/null +++ b/external/boringssl/crypto/x509/algorithm.c @@ -0,0 +1,137 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) { + const EVP_MD *digest = EVP_MD_CTX_md(ctx); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + if (digest == NULL || pkey == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED); + return 0; + } + + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + int pad_mode; + if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) { + return 0; + } + /* RSA-PSS has special signature algorithm logic. */ + if (pad_mode == RSA_PKCS1_PSS_PADDING) { + return x509_rsa_ctx_to_pss(ctx, algor); + } + } + + /* Default behavior: look up the OID for the algorithm/hash pair and encode + * that. */ + int sign_nid; + if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest), + EVP_PKEY_id(pkey))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + return 0; + } + + /* RSA signature algorithms include an explicit NULL parameter. Others omit + * it. */ + int paramtype = + (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF; + X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL); + return 1; +} + +int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, + EVP_PKEY *pkey) { + /* Convert the signature OID into digest and public key OIDs. */ + int sigalg_nid = OBJ_obj2nid(sigalg->algorithm); + int digest_nid, pkey_nid; + if (!OBJ_find_sigid_algs(sigalg_nid, &digest_nid, &pkey_nid)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + return 0; + } + + /* Check the public key OID matches the public key type. */ + if (pkey_nid != EVP_PKEY_id(pkey)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE); + return 0; + } + + /* NID_undef signals that there are custom parameters to set. */ + if (digest_nid == NID_undef) { + if (sigalg_nid != NID_rsassaPss) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + return 0; + } + return x509_rsa_pss_to_ctx(ctx, sigalg, pkey); + } + + /* Otherwise, initialize with the digest from the OID. */ + const EVP_MD *digest = EVP_get_digestbynid(digest_nid); + if (digest == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + return 0; + } + + return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey); +} diff --git a/external/boringssl/crypto/x509/asn1_gen.c b/external/boringssl/crypto/x509/asn1_gen.c new file mode 100644 index 0000000000..03a0ab9feb --- /dev/null +++ b/external/boringssl/crypto/x509/asn1_gen.c @@ -0,0 +1,818 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "../internal.h" + +/* + * Although this file is in crypto/x509 for layering purposes, it emits + * errors from the ASN.1 module for OpenSSL compatibility. + */ + +#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 = 0; + int hdr_constructed = 0, hdr_tag, hdr_class; + int r; + + asn1_tags.imp_tag = -1; + asn1_tags.imp_class = -1; + asn1_tags.format = ASN1_GEN_FORMAT_ASCII; + asn1_tags.exp_count = 0; + if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) + return NULL; + + if ((asn1_tags.utype == V_ASN1_SEQUENCE) + || (asn1_tags.utype == V_ASN1_SET)) { + if (!cnf) { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, 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(ASN1, 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(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING); + return -1; + } + if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) + return -1; + break; + + case ASN1_GEN_FLAG_EXP: + + if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) + return -1; + if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) + return -1; + break; + + case ASN1_GEN_FLAG_SEQWRAP: + if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_SETWRAP: + if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_BITWRAP: + if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_OCTWRAP: + if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_FORMAT: + if (!vstart) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + if (!strncmp(vstart, "ASCII", 5)) + arg->format = ASN1_GEN_FORMAT_ASCII; + else if (!strncmp(vstart, "UTF8", 4)) + arg->format = ASN1_GEN_FORMAT_UTF8; + else if (!strncmp(vstart, "HEX", 3)) + arg->format = ASN1_GEN_FORMAT_HEX; + else if (!strncmp(vstart, "BITLIST", 7)) + arg->format = ASN1_GEN_FORMAT_BITLIST; + else { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, 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(ASN1, 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(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG); + return 0; + } + + if (arg->exp_count == ASN1_FLAG_EXP_MAX) { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!str) + str = ""; + + switch (utype) { + + case V_ASN1_NULL: + if (str && *str) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE); + goto bad_form; + } + break; + + case V_ASN1_BOOLEAN: + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT); + goto bad_form; + } + vtmp.name = NULL; + vtmp.section = NULL; + vtmp.value = (char *)str; + if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER); + goto bad_str; + } + break; + + case V_ASN1_OBJECT: + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.object = OBJ_txt2obj(str, 0))) { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.asn1_string = ASN1_STRING_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + atmp->value.asn1_string->type = utype; + if (!ASN1_TIME_check(atmp->value.asn1_string)) { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, ASN1_R_ILLEGAL_FORMAT); + goto bad_form; + } + + if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, + -1, format, ASN1_tag2bit(utype)) <= 0) { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_form; + } + + if (format == ASN1_GEN_FORMAT_HEX) { + + if (!(rdata = string_to_hex((char *)str, &rdlen))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX); + goto bad_str; + } + + atmp->value.asn1_string->data = rdata; + atmp->value.asn1_string->length = rdlen; + atmp->value.asn1_string->type = utype; + + } else if (format == ASN1_GEN_FORMAT_ASCII) + ASN1_STRING_set(atmp->value.asn1_string, str, -1); + else if ((format == ASN1_GEN_FORMAT_BITLIST) + && (utype == V_ASN1_BIT_STRING)) { + if (!CONF_parse_list + (str, ',', 1, bitstr_cb, atmp->value.bit_string)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR); + goto bad_str; + } + no_unused = 0; + + } else { + OPENSSL_PUT_ERROR(ASN1, 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(ASN1, 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(ASN1, ASN1_R_INVALID_NUMBER); + return 0; + } + if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} diff --git a/external/boringssl/crypto/x509/by_dir.c b/external/boringssl/crypto/x509/by_dir.c new file mode 100644 index 0000000000..4445b058a2 --- /dev/null +++ b/external/boringssl/crypto/x509/by_dir.c @@ -0,0 +1,453 @@ +/* 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +typedef struct lookup_dir_hashes_st { + unsigned long hash; + int suffix; +} BY_DIR_HASH; + +typedef struct lookup_dir_entry_st { + char *dir; + int dir_type; + STACK_OF(BY_DIR_HASH) *hashes; +} BY_DIR_ENTRY; + +typedef struct lookup_dir_st { + BUF_MEM *buffer; + STACK_OF(BY_DIR_ENTRY) *dirs; +} BY_DIR; + +DECLARE_STACK_OF(BY_DIR_HASH) +DECLARE_STACK_OF(BY_DIR_ENTRY) + +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret); +static int new_dir(X509_LOOKUP *lu); +static void free_dir(X509_LOOKUP *lu); +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type); +static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, + X509_OBJECT *ret); +static X509_LOOKUP_METHOD x509_dir_lookup = { + "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, 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, 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, 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; +} + +/* + * g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY| + * objects. + */ +static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock = + CRYPTO_STATIC_MUTEX_INIT; + +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, X509_R_WRONG_LOOKUP_TYPE); + goto finish; + } + + if ((b = BUF_MEM_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, 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, ERR_R_MALLOC_FAILURE); + goto finish; + } + if (type == X509_LU_CRL && ent->hashes) { + htmp.hash = h; + CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock); + 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_STATIC_MUTEX_unlock_read(&g_ent_hashes_lock); + } 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_MUTEX_lock_write(&xl->store_ctx->objs_lock); + tmp = NULL; + if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) { + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx); + } + CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock); + + /* + * If a CRL, update the last file suffix added for this + */ + + if (type == X509_LU_CRL) { + CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock); + /* + * 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)); + if (hent == NULL) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + ok = 0; + goto finish; + } + hent->hash = h; + hent->suffix = k; + if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + OPENSSL_free(hent); + ok = 0; + goto finish; + } + } else if (hent->suffix < k) + hent->suffix = k; + + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + } + + 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/external/boringssl/crypto/x509/by_file.c b/external/boringssl/crypto/x509/by_file.c new file mode 100644 index 0000000000..ebeb72e5e8 --- /dev/null +++ b/external/boringssl/crypto/x509/by_file.c @@ -0,0 +1,275 @@ +/* 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 + +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_STDIO + +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); +static 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, 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, 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, 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, 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_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, 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, 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, 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_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, 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, 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/external/boringssl/crypto/x509/charmap.h b/external/boringssl/crypto/x509/charmap.h new file mode 100644 index 0000000000..3305ad146b --- /dev/null +++ b/external/boringssl/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/external/boringssl/crypto/x509/i2d_pr.c b/external/boringssl/crypto/x509/i2d_pr.c new file mode 100644 index 0000000000..c3fb8a8a63 --- /dev/null +++ b/external/boringssl/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 +#include +#include +#include +#include +#include + + +int i2d_PrivateKey(const EVP_PKEY *a, uint8_t **pp) +{ + switch (EVP_PKEY_id(a)) { + case EVP_PKEY_RSA: + return i2d_RSAPrivateKey(a->pkey.rsa, pp); + case EVP_PKEY_EC: + return i2d_ECPrivateKey(a->pkey.ec, pp); + case EVP_PKEY_DSA: + return i2d_DSAPrivateKey(a->pkey.dsa, pp); + default: + /* + * Although this file is in crypto/x509 for layering reasons, it emits + * an error code from ASN1 for OpenSSL compatibility. + */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; + } +} diff --git a/external/boringssl/crypto/x509/internal.h b/external/boringssl/crypto/x509/internal.h new file mode 100644 index 0000000000..4957c1e147 --- /dev/null +++ b/external/boringssl/crypto/x509/internal.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2016, 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_X509_INTERNAL_H +#define OPENSSL_HEADER_X509_INTERNAL_H + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* RSA-PSS functions. */ + +/* x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on + * signature algorithm parameters in |sigalg| (which must have type + * |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on + * error. */ +int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey); + +/* x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for + * |ctx|, which must have been configured for an RSA-PSS signing operation. It + * returns one on success and zero on error. */ +int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor); + +/* x509_print_rsa_pss_params prints a human-readable representation of RSA-PSS + * parameters in |sigalg| to |bp|. It returns one on success and zero on + * error. */ +int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, + ASN1_PCTX *pctx); + + +/* Signature algorithm functions. */ + +/* x509_digest_sign_algorithm encodes the signing parameters of |ctx| as an + * AlgorithmIdentifer and saves the result in |algor|. It returns one on + * success, or zero on error. */ +int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor); + +/* x509_digest_verify_init 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. */ +int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, + EVP_PKEY *pkey); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_X509_INTERNAL_H */ diff --git a/external/boringssl/crypto/x509/pkcs7.c b/external/boringssl/crypto/x509/pkcs7.c new file mode 100644 index 0000000000..9e6a52f26e --- /dev/null +++ b/external/boringssl/crypto/x509/pkcs7.c @@ -0,0 +1,353 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../bytestring/internal.h" + + +/* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7 + * SignedData blob from |cbs| and sets |*out| to point to the rest of the + * input. If the input is in BER format, then |*der_bytes| will be set to a + * pointer that needs to be freed by the caller once they have finished + * processing |*out| (which will be pointing into |*der_bytes|). + * + * It returns one on success or zero on error. On error, |*der_bytes| is + * NULL. */ +static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) { + size_t der_len; + CBS in, content_info, content_type, wrapped_signed_data, signed_data; + uint64_t version; + + /* The input may be in BER format. */ + *der_bytes = NULL; + 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, 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, X509_R_BAD_PKCS7_VERSION); + goto err; + } + + CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data)); + return 1; + +err: + if (*der_bytes) { + OPENSSL_free(*der_bytes); + *der_bytes = NULL; + } + + return 0; +} + +int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) { + CBS signed_data, certificates; + uint8_t *der_bytes = NULL; + int ret = 0; + const size_t initial_certs_len = sk_X509_num(out_certs); + + if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { + return 0; + } + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + if (!CBS_get_asn1(&signed_data, &certificates, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + OPENSSL_PUT_ERROR(X509, 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; + } + + if (CBS_len(&cert) > LONG_MAX) { + goto err; + } + inp = CBS_data(&cert); + x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert)); + if (!x509) { + goto err; + } + + assert(inp == CBS_data(&cert) + CBS_len(&cert)); + + if (sk_X509_push(out_certs, x509) == 0) { + X509_free(x509); + goto err; + } + } + + 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_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) { + CBS signed_data, crls; + uint8_t *der_bytes = NULL; + int ret = 0; + const size_t initial_crls_len = sk_X509_CRL_num(out_crls); + + if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { + return 0; + } + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + + /* Even if only CRLs are included, there may be an empty certificates block. + * OpenSSL does this, for example. */ + if (CBS_peek_asn1_tag(&signed_data, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) && + !CBS_get_asn1(&signed_data, NULL /* certificates */, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + goto err; + } + + if (!CBS_get_asn1(&signed_data, &crls, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CRLS_INCLUDED); + goto err; + } + + while (CBS_len(&crls) > 0) { + CBS crl_data; + X509_CRL *crl; + const uint8_t *inp; + + if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) { + goto err; + } + + if (CBS_len(&crl_data) > LONG_MAX) { + goto err; + } + inp = CBS_data(&crl_data); + crl = d2i_X509_CRL(NULL, &inp, (long)CBS_len(&crl_data)); + if (!crl) { + goto err; + } + + assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data)); + + if (sk_X509_CRL_push(out_crls, crl) == 0) { + X509_CRL_free(crl); + goto err; + } + } + + ret = 1; + +err: + if (der_bytes) { + OPENSSL_free(der_bytes); + } + + if (!ret) { + while (sk_X509_CRL_num(out_crls) != initial_crls_len) { + X509_CRL_free(sk_X509_CRL_pop(out_crls)); + } + } + + return ret; +} + +int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) { + uint8_t *data; + long len; + int ret; + + /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM + * internally will actually allow several other values too, including + * "CERTIFICATE". */ + if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */, + PEM_STRING_PKCS7, pem_bio, + NULL /* password callback */, + NULL /* password callback argument */)) { + return 0; + } + + CBS cbs; + CBS_init(&cbs, data, len); + ret = PKCS7_get_certificates(out_certs, &cbs); + OPENSSL_free(data); + return ret; +} + +int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) { + uint8_t *data; + long len; + int ret; + + /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM + * internally will actually allow several other values too, including + * "CERTIFICATE". */ + if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */, + PEM_STRING_PKCS7, pem_bio, + NULL /* password callback */, + NULL /* password callback argument */)) { + return 0; + } + + CBS cbs; + CBS_init(&cbs, data, len); + ret = PKCS7_get_CRLs(out_crls, &cbs); + OPENSSL_free(data); + return ret; +} + +/* pkcs7_bundle writes a PKCS#7, SignedData structure to |out| and then calls + * |cb| with a CBB to which certificate or CRL data can be written, and the + * opaque context pointer, |arg|. The callback can return zero to indicate an + * error. + * + * pkcs7_bundle returns one on success or zero on error. */ +static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg), + const void *arg) { + CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set, + content_info; + + /* 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) || + !cb(&seq, arg)) { + return 0; + } + + return CBB_flush(out); +} + +static int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) { + const STACK_OF(X509) *certs = arg; + size_t i; + CBB certificates; + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + if (!CBB_add_asn1(out, &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); +} + +int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) { + return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs); +} + +static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) { + const STACK_OF(X509_CRL) *crls = arg; + size_t i; + CBB crl_data; + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + if (!CBB_add_asn1(out, &crl_data, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { + return 0; + } + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + X509_CRL *crl = sk_X509_CRL_value(crls, i); + uint8_t *buf; + int len = i2d_X509_CRL(crl, NULL); + + if (len < 0 || + !CBB_add_space(&crl_data, &buf, len) || + i2d_X509_CRL(crl, &buf) < 0) { + return 0; + } + } + + return CBB_flush(out); +} + +int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) { + return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls); +} diff --git a/external/boringssl/crypto/x509/pkcs7_test.c b/external/boringssl/crypto/x509/pkcs7_test.c new file mode 100644 index 0000000000..bebcbd9555 --- /dev/null +++ b/external/boringssl/crypto/x509/pkcs7_test.c @@ -0,0 +1,656 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../test/test_util.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, +}; + +/* kOpenSSLCRL is the Equifax CRL, converted to PKCS#7 form by: + * openssl crl2pkcs7 -inform DER -in secureca.crl */ +static const uint8_t kOpenSSLCRL[] = { + 0x30, 0x82, 0x03, 0x85, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x02, 0xa0, 0x82, 0x03, 0x76, 0x30, 0x82, 0x03, 0x72, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x00, 0xa1, 0x82, 0x03, 0x58, 0x30, + 0x82, 0x03, 0x54, 0x30, 0x82, 0x02, 0xbd, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4e, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, + 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, + 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x32, + 0x32, 0x37, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, + 0x35, 0x30, 0x33, 0x30, 0x39, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a, + 0x30, 0x82, 0x02, 0x3c, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x58, 0xe4, 0x17, + 0x0d, 0x31, 0x34, 0x30, 0x34, 0x32, 0x37, 0x30, 0x38, 0x31, 0x39, 0x32, + 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x76, 0x19, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x36, 0x31, 0x38, 0x31, 0x35, 0x30, 0x30, 0x30, 0x33, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x0f, 0x9a, 0xfb, 0x17, 0x0d, 0x31, 0x34, 0x30, + 0x34, 0x32, 0x39, 0x31, 0x38, 0x30, 0x39, 0x31, 0x37, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x14, 0x8b, 0xc0, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x30, + 0x39, 0x31, 0x39, 0x34, 0x36, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x14, 0xe4, 0x9c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x31, 0x36, 0x32, + 0x33, 0x33, 0x39, 0x33, 0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x86, + 0x07, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x31, 0x31, 0x35, 0x35, + 0x30, 0x35, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xe2, 0x29, 0x17, + 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31, 0x38, 0x35, 0x35, 0x31, + 0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0d, 0x42, 0x66, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x35, 0x33, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x03, 0x1e, 0x33, 0x17, 0x0d, 0x30, 0x32, 0x30, + 0x35, 0x31, 0x35, 0x31, 0x33, 0x30, 0x36, 0x31, 0x31, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x12, 0xe2, 0x23, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30, + 0x36, 0x32, 0x30, 0x34, 0x30, 0x32, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x13, 0x9c, 0xab, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x37, 0x32, 0x39, 0x31, + 0x36, 0x34, 0x34, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xc6, + 0x0a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30, 0x36, 0x32, 0x32, 0x32, + 0x31, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x03, 0x25, 0x85, 0x17, + 0x0d, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x31, 0x38, 0x31, 0x31, 0x35, + 0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x86, 0xe6, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x37, 0x32, 0x35, 0x30, 0x32, 0x30, 0x30, 0x33, 0x38, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x13, 0x9c, 0xa1, 0x17, 0x0d, 0x31, 0x30, 0x30, + 0x37, 0x32, 0x39, 0x31, 0x36, 0x34, 0x37, 0x33, 0x32, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x15, 0x4d, 0x5c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x33, + 0x30, 0x30, 0x30, 0x30, 0x34, 0x34, 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x0f, 0xfa, 0x2d, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31, + 0x38, 0x35, 0x30, 0x31, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x13, 0x75, + 0x55, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x31, 0x31, 0x38, 0x30, 0x32, 0x32, + 0x31, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x56, 0x96, 0x17, + 0x0d, 0x31, 0x34, 0x30, 0x36, 0x32, 0x34, 0x31, 0x32, 0x33, 0x31, 0x30, + 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0b, 0x80, 0x8a, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x32, 0x35, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x0f, 0x94, 0x16, 0x17, 0x0d, 0x31, 0x30, 0x30, + 0x33, 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x33, 0x31, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x14, 0x16, 0xb3, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, + 0x38, 0x31, 0x34, 0x33, 0x32, 0x35, 0x36, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x0a, 0xe1, 0x85, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, 0x32, 0x37, 0x31, + 0x37, 0x31, 0x30, 0x31, 0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0xcc, + 0x3e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x31, 0x31, 0x32, 0x35, + 0x35, 0x33, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x10, 0x5b, 0xcb, 0x17, + 0x0d, 0x31, 0x30, 0x30, 0x37, 0x33, 0x30, 0x32, 0x31, 0x33, 0x31, 0x32, + 0x30, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x15, 0x6a, 0x1f, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x32, 0x32, 0x36, 0x31, 0x32, 0x33, 0x35, 0x31, 0x39, 0x5a, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x1d, 0x5c, 0x27, 0x07, 0x11, + 0x03, 0xf2, 0x00, 0xbd, 0xf4, 0x46, 0x3e, 0x71, 0xfd, 0x10, 0x84, 0x83, + 0xd9, 0xd2, 0xd2, 0x19, 0xa0, 0x20, 0xf7, 0x1a, 0x43, 0x3d, 0xac, 0xda, + 0x33, 0xfc, 0xb7, 0x42, 0x60, 0x1a, 0xa4, 0xa8, 0xb2, 0x07, 0x5c, 0x51, + 0x16, 0xc0, 0x42, 0x80, 0x0a, 0x0f, 0xf0, 0x47, 0x5b, 0x4b, 0x78, 0x90, + 0xaf, 0xc7, 0xac, 0x48, 0xf8, 0xca, 0x3c, 0x13, 0x5e, 0xf6, 0xd1, 0x88, + 0xae, 0x55, 0xa3, 0x0c, 0x8a, 0x62, 0x47, 0x29, 0xf8, 0x72, 0xb8, 0x24, + 0x17, 0xaf, 0xb2, 0x06, 0x1e, 0xa7, 0x72, 0x76, 0xab, 0x96, 0x1d, 0xe0, + 0x7c, 0xd4, 0x0c, 0x42, 0x82, 0x3d, 0x4a, 0x8e, 0x15, 0x77, 0x2f, 0x3c, + 0x2a, 0x8c, 0x3a, 0x04, 0x10, 0x55, 0xdc, 0xbb, 0xba, 0xb1, 0x91, 0xee, + 0x7b, 0xe7, 0x23, 0xc5, 0x71, 0x13, 0xae, 0x6b, 0x21, 0x35, 0xd3, 0x64, + 0xf0, 0x00, 0x54, 0x31, 0x00, +}; + +/* kPEMCert is the result of exporting the mail.google.com certificate from + * Chrome and then running it through: + * openssl pkcs7 -inform DER -in mail.google.com -outform PEM */ +static const char kPEMCert[] = + "-----BEGIN PKCS7-----\n" + "MIID+wYJKoZIhvcNAQcCoIID7DCCA+gCAQExADALBgkqhkiG9w0BBwGgggPQMIID\n" + "zDCCArSgAwIBAgIIWesoywKxoNQwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UEBhMC\n" + "VVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5l\n" + "dCBBdXRob3JpdHkgRzIwHhcNMTUwMjExMTQxNTA2WhcNMTUwNTEyMDAwMDAwWjBp\n" + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91\n" + "bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEYMBYGA1UEAwwPbWFpbC5n\n" + "b29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7MdALmCkcRRf/tzQ\n" + "a8eu3J7S5CTQa5ns0ReF9ktlbB1RL56BVGAu4p7BrT32D6gDpiggXq3gxN81A0TG\n" + "C2yICKOCAWEwggFdMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAsBgNV\n" + "HREEJTAjgg9tYWlsLmdvb2dsZS5jb22CEGluYm94Lmdvb2dsZS5jb20wCwYDVR0P\n" + "BAQDAgeAMGgGCCsGAQUFBwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5n\n" + "b29nbGUuY29tL0dJQUcyLmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMx\n" + "Lmdvb2dsZS5jb20vb2NzcDAdBgNVHQ4EFgQUQqsYsRoWLiG6qmV2N1mpYaHawxAw\n" + "DAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAX\n" + "BgNVHSAEEDAOMAwGCisGAQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDov\n" + "L3BraS5nb29nbGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAKNh3\n" + "isNuGBisPKVlekOsZR6S8oP/fS/xt6Hqvg0EwFXvhxoJ40rxAB2LMykY17e+ln3P\n" + "MwBBlRkwY1btcDT15JwzgaZb38rq/r+Pkb5Qgmx/InA/pw0QHDtwHQp5uXZuvu6p\n" + "J/SlCwyq7EOvByWdVQcMU/dhGa3idXEkn/zwfqcG6YjdWKoDmXWZYv3RiP3wJcRB\n" + "9+3U1wOe3uebnZLRWO6/w0to1XY8TFHklyw5rwIE5sbxOx5N3Ne8+GgPrUDvGAz0\n" + "rAUKnh3b7GNXL1qlZh2qkhB6rUzvtPpg397Asg3xVtExCHOk4zPqzzicttoEbVVy\n" + "0T8rIMUNwC4Beh4JVjEA\n" + "-----END PKCS7-----\n"; + +/* kPEMCRL is the result of downloading the Equifax CRL and running: + openssl crl2pkcs7 -inform DER -in secureca.crl */ +static const char kPEMCRL[] = + "-----BEGIN PKCS7-----\n" + "MIIDhQYJKoZIhvcNAQcCoIIDdjCCA3ICAQExADALBgkqhkiG9w0BBwGgAKGCA1gw\n" + "ggNUMIICvTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UEChMH\n" + "RXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0\n" + "aG9yaXR5Fw0xNTAyMjcwMTIzMDBaFw0xNTAzMDkwMTIzMDBaMIICPDAUAgMPWOQX\n" + "DTE0MDQyNzA4MTkyMlowFAIDFHYZFw0xNDA2MTgxNTAwMDNaMBQCAw+a+xcNMTQw\n" + "NDI5MTgwOTE3WjAUAgMUi8AXDTE0MDcwOTE5NDYzM1owFAIDFOScFw0xNDA0MTYy\n" + "MzM5MzVaMBQCAw+GBxcNMTQwNTIxMTU1MDUzWjAUAgMS4ikXDTE0MDYxNzE4NTUx\n" + "NVowFAIDDUJmFw0xMjA2MjcxNzEwNTNaMBQCAwMeMxcNMDIwNTE1MTMwNjExWjAU\n" + "AgMS4iMXDTE0MDYwNjIwNDAyMVowFAIDE5yrFw0xMDA3MjkxNjQ0MzlaMBQCAxLG\n" + "ChcNMTQwNjA2MjIyMTM5WjAUAgMDJYUXDTAyMDUxNDE4MTE1N1owFAIDFIbmFw0x\n" + "NDA3MjUwMjAwMzhaMBQCAxOcoRcNMTAwNzI5MTY0NzMyWjAUAgMVTVwXDTE0MDQz\n" + "MDAwMDQ0MlowFAIDD/otFw0xNDA2MTcxODUwMTFaMBQCAxN1VRcNMTUwMTE4MDIy\n" + "MTMzWjAUAgMPVpYXDTE0MDYyNDEyMzEwMlowFAIDC4CKFw0xMjA2MjcxNzEwMjVa\n" + "MBQCAw+UFhcNMTAwMzAxMTM0NTMxWjAUAgMUFrMXDTE0MDYxODE0MzI1NlowFAID\n" + "CuGFFw0xMjA2MjcxNzEwMTdaMBQCAxTMPhcNMTQwNzExMTI1NTMxWjAUAgMQW8sX\n" + "DTEwMDczMDIxMzEyMFowFAIDFWofFw0xNDAyMjYxMjM1MTlaMA0GCSqGSIb3DQEB\n" + "BQUAA4GBAB1cJwcRA/IAvfRGPnH9EISD2dLSGaAg9xpDPazaM/y3QmAapKiyB1xR\n" + "FsBCgAoP8EdbS3iQr8esSPjKPBNe9tGIrlWjDIpiRyn4crgkF6+yBh6ncnarlh3g\n" + "fNQMQoI9So4Vdy88Kow6BBBV3Lu6sZHue+cjxXETrmshNdNk8ABUMQA=\n" + "-----END PKCS7-----\n"; + +static int test_cert_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 %zu differs.\n", 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; +} + +static int test_crl_reparse(const uint8_t *der_bytes, size_t der_len) { + CBS pkcs7; + CBB cbb; + STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null(); + STACK_OF(X509_CRL) *crls2 = sk_X509_CRL_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_CRLs(crls, &pkcs7)) { + fprintf(stderr, "PKCS7_get_CRLs failed.\n"); + return 0; + } + + CBB_init(&cbb, der_len); + if (!PKCS7_bundle_CRLs(&cbb, crls) || + !CBB_finish(&cbb, &result_data, &result_len)) { + fprintf(stderr, "PKCS7_bundle_CRLs failed.\n"); + return 0; + } + + CBS_init(&pkcs7, result_data, result_len); + if (!PKCS7_get_CRLs(crls2, &pkcs7)) { + fprintf(stderr, "PKCS7_get_CRLs reparse failed.\n"); + return 0; + } + + if (sk_X509_CRL_num(crls) != sk_X509_CRL_num(crls)) { + fprintf(stderr, "Number of CRLs in results differ.\n"); + return 0; + } + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + X509_CRL *a = sk_X509_CRL_value(crls, i); + X509_CRL *b = sk_X509_CRL_value(crls2, i); + + if (X509_CRL_cmp(a, b) != 0) { + fprintf(stderr, "CRL %zu differs.\n", i); + return 0; + } + } + + CBB_init(&cbb, der_len); + if (!PKCS7_bundle_CRLs(&cbb, crls2) || + !CBB_finish(&cbb, &result2_data, &result2_len)) { + fprintf(stderr, + "PKCS7_bundle_CRLs 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_CRL_pop_free(crls, X509_CRL_free); + sk_X509_CRL_pop_free(crls2, X509_CRL_free); + + return 1; +} + +static int test_pem_certs(const char *pem) { + BIO *bio = BIO_new_mem_buf(pem, strlen(pem)); + STACK_OF(X509) *certs = sk_X509_new_null(); + + if (!PKCS7_get_PEM_certificates(certs, bio)) { + fprintf(stderr, "PKCS7_get_PEM_certificates failed.\n"); + return 0; + } + + if (sk_X509_num(certs) != 1) { + fprintf(stderr, + "Bad number of certificates from PKCS7_get_PEM_certificates: %zu\n", + sk_X509_num(certs)); + return 0; + } + + BIO_free(bio); + sk_X509_pop_free(certs, X509_free); + + return 1; +} + +static int test_pem_crls(const char *pem) { + BIO *bio = BIO_new_mem_buf(pem, strlen(pem)); + STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null(); + + if (!PKCS7_get_PEM_CRLs(crls, bio)) { + fprintf(stderr, "PKCS7_get_PEM_CRLs failed.\n"); + return 0; + } + + if (sk_X509_CRL_num(crls) != 1) { + fprintf(stderr, "Bad number of CRLs from PKCS7_get_PEM_CRLs: %zu\n", + sk_X509_CRL_num(crls)); + return 0; + } + + BIO_free(bio); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + + return 1; +} + +int main(void) { + CRYPTO_library_init(); + + if (!test_cert_reparse(kPKCS7NSS, sizeof(kPKCS7NSS)) || + !test_cert_reparse(kPKCS7Windows, sizeof(kPKCS7Windows)) || + !test_crl_reparse(kOpenSSLCRL, sizeof(kOpenSSLCRL)) || + !test_pem_certs(kPEMCert) || + !test_pem_crls(kPEMCRL)) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/x509/rsa_pss.c b/external/boringssl/crypto/x509/rsa_pss.c new file mode 100644 index 0000000000..1ae01a3d26 --- /dev/null +++ b/external/boringssl/crypto/x509/rsa_pss.c @@ -0,0 +1,385 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +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); + + +/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */ +static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) { + if (alg == NULL || alg->parameter == NULL || + OBJ_obj2nid(alg->algorithm) != NID_mgf1 || + alg->parameter->type != V_ASN1_SEQUENCE) { + return NULL; + } + + const uint8_t *p = alg->parameter->value.sequence->data; + int 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) { + *pmaskHash = NULL; + + if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) { + return NULL; + } + + const uint8_t *p = alg->parameter->value.sequence->data; + int plen = alg->parameter->value.sequence->length; + RSA_PSS_PARAMS *pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen); + if (pss == NULL) { + return NULL; + } + + *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm); + return pss; +} + +/* 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 == NULL) { + return 0; + } + X509_ALGOR_set_md(*palg, md); + return 1; +} + +/* Allocate and set MGF1 algorithm ID from EVP_MD */ +static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) { + X509_ALGOR *algtmp = NULL; + ASN1_STRING *stmp = NULL; + *palg = NULL; + + if (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: + ASN1_STRING_free(stmp); + X509_ALGOR_free(algtmp); + if (*palg) { + return 1; + } + + return 0; +} + +/* convert algorithm ID to EVP_MD, default SHA1 */ +static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) { + const EVP_MD *md; + if (!alg) { + return EVP_sha1(); + } + md = EVP_get_digestbyobj(alg->algorithm); + if (md == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + } + 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 || + maskHash == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + return NULL; + } + md = EVP_get_digestbyobj(maskHash->algorithm); + if (md == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + return NULL; + } + return md; +} + +int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) { + const EVP_MD *sigmd, *mgf1md; + int saltlen; + if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) || + !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) || + !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) { + return 0; + } + + EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + 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 { + return 0; + } + + int ret = 0; + ASN1_STRING *os = NULL; + RSA_PSS_PARAMS *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; + } + + X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os); + os = NULL; + ret = 1; + +err: + RSA_PSS_PARAMS_free(pss); + ASN1_STRING_free(os); + return ret; +} + +int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { + assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); + + /* Decode PSS parameters */ + int ret = 0; + X509_ALGOR *maskHash; + RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); + if (pss == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + goto err; + } + + const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); + const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm); + if (mgf1md == NULL || md == NULL) { + goto err; + } + + int saltlen = 20; + if (pss->saltLength != NULL) { + 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(X509, X509_R_INVALID_PSS_PARAMETERS); + 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 != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + goto err; + } + + EVP_PKEY_CTX *pkctx; + if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) || + !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) || + !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) { + goto err; + } + + ret = 1; + +err: + RSA_PSS_PARAMS_free(pss); + X509_ALGOR_free(maskHash); + return ret; +} + +int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, + ASN1_PCTX *pctx) { + assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); + + int rv = 0; + X509_ALGOR *maskHash; + RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); + if (!pss) { + if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) { + goto err; + } + rv = 1; + goto err; + } + + 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: + RSA_PSS_PARAMS_free(pss); + X509_ALGOR_free(maskHash); + return rv; +} diff --git a/external/boringssl/crypto/x509/t_crl.c b/external/boringssl/crypto/x509/t_crl.c new file mode 100644 index 0000000000..6c347cb845 --- /dev/null +++ b/external/boringssl/crypto/x509/t_crl.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 +#include +#include +#include +#include +#include + +#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, 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/external/boringssl/crypto/x509/t_req.c b/external/boringssl/crypto/x509/t_req.c new file mode 100644 index 0000000000..39c836ccc6 --- /dev/null +++ b/external/boringssl/crypto/x509/t_req.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include + + +int X509_REQ_print_fp(FILE *fp, X509_REQ *x) { + BIO *bio = BIO_new(BIO_s_file()); + if (bio == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return 0; + } + + BIO_set_fp(bio, fp, BIO_NOCLOSE); + int ret = X509_REQ_print(bio, x); + BIO_free(bio); + return ret; +} + +int X509_REQ_print_ex(BIO *bio, X509_REQ *x, unsigned long nmflags, + unsigned long cflag) { + long l; + EVP_PKEY *pkey; + STACK_OF(X509_ATTRIBUTE) * sk; + char mlch = ' '; + + int nmindent = 0; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) { + nmindent = 16; + } + + X509_REQ_INFO *ri = x->req_info; + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bio, "Certificate Request:\n", 21) <= 0 || + BIO_write(bio, " Data:\n", 10) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_REQ_get_version(x); + if (BIO_printf(bio, "%8sVersion: %ld (0x%lx)\n", "", l + 1, l) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bio, " Subject:%c", mlch) <= 0 || + X509_NAME_print_ex(bio, ri->subject, nmindent, nmflags) < 0 || + BIO_write(bio, "\n", 1) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + if (BIO_write(bio, " Subject Public Key Info:\n", 33) <= 0 || + BIO_printf(bio, "%12sPublic Key Algorithm: ", "") <= 0 || + i2a_ASN1_OBJECT(bio, ri->pubkey->algor->algorithm) <= 0 || + BIO_puts(bio, "\n") <= 0) { + goto err; + } + + pkey = X509_REQ_get_pubkey(x); + if (pkey == NULL) { + BIO_printf(bio, "%12sUnable to load Public Key\n", ""); + ERR_print_errors(bio); + } else { + EVP_PKEY_print_public(bio, pkey, 16, NULL); + EVP_PKEY_free(pkey); + } + } + + if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) { + if (BIO_printf(bio, "%8sAttributes:\n", "") <= 0) { + goto err; + } + + sk = x->req_info->attributes; + if (sk_X509_ATTRIBUTE_num(sk) == 0) { + if (BIO_printf(bio, "%12sa0:00\n", "") <= 0) { + goto err; + } + } else { + size_t i; + for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { + X509_ATTRIBUTE *a = sk_X509_ATTRIBUTE_value(sk, i); + ASN1_OBJECT *aobj = X509_ATTRIBUTE_get0_object(a); + + if (X509_REQ_extension_nid(OBJ_obj2nid(aobj))) { + continue; + } + + if (BIO_printf(bio, "%12s", "") <= 0) { + goto err; + } + + const int num_attrs = X509_ATTRIBUTE_count(a); + const int obj_str_len = i2a_ASN1_OBJECT(bio, aobj); + if (obj_str_len <= 0) { + if (BIO_puts(bio, "(Unable to print attribute ID.)\n") < 0) { + goto err; + } else { + continue; + } + } + + int j; + for (j = 0; j < num_attrs; j++) { + const ASN1_TYPE *at = X509_ATTRIBUTE_get0_type(a, j); + const int type = at->type; + ASN1_BIT_STRING *bs = at->value.asn1_string; + + int k; + for (k = 25 - obj_str_len; k > 0; k--) { + if (BIO_write(bio, " ", 1) != 1) { + goto err; + } + } + + if (BIO_puts(bio, ":") <= 0) { + goto err; + } + + if (type == V_ASN1_PRINTABLESTRING || + type == V_ASN1_UTF8STRING || + type == V_ASN1_IA5STRING || + type == V_ASN1_T61STRING) { + if (BIO_write(bio, (char *)bs->data, bs->length) != bs->length) { + goto err; + } + BIO_puts(bio, "\n"); + } else { + BIO_puts(bio, "unable to print attribute\n"); + } + } + } + } + } + + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { + STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(x); + if (exts) { + BIO_printf(bio, "%8sRequested Extensions:\n", ""); + + size_t i; + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i); + if (BIO_printf(bio, "%12s", "") <= 0) { + goto err; + } + ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); + i2a_ASN1_OBJECT(bio, obj); + const int is_critical = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bio, ": %s\n", is_critical ? "critical" : "") <= 0) { + goto err; + } + if (!X509V3_EXT_print(bio, ex, cflag, 16)) { + BIO_printf(bio, "%16s", ""); + ASN1_STRING_print(bio, X509_EXTENSION_get_data(ex)); + } + if (BIO_write(bio, "\n", 1) <= 0) { + goto err; + } + } + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + } + } + + if (!(cflag & X509_FLAG_NO_SIGDUMP) && + !X509_signature_print(bio, x->sig_alg, x->signature)) { + goto err; + } + + return 1; + +err: + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return 0; +} + +int X509_REQ_print(BIO *bio, X509_REQ *req) { + return X509_REQ_print_ex(bio, req, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} diff --git a/external/boringssl/crypto/x509/t_x509.c b/external/boringssl/crypto/x509/t_x509.c new file mode 100644 index 0000000000..1fba9b4335 --- /dev/null +++ b/external/boringssl/crypto/x509/t_x509.c @@ -0,0 +1,506 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "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, 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) + || (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) { + 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) +{ + if (BIO_puts(bp, " Signature Algorithm: ") <= 0) + return 0; + if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) + return 0; + + /* RSA-PSS signatures have parameters to print. */ + int sig_nid = OBJ_obj2nid(sigalg->algorithm); + if (sig_nid == NID_rsassaPss && + !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) { + return 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, ERR_R_BUF_LIB); + } + OPENSSL_free(b); + return (ret); +} diff --git a/external/boringssl/crypto/x509/t_x509a.c b/external/boringssl/crypto/x509/t_x509a.c new file mode 100644 index 0000000000..54368286ba --- /dev/null +++ b/external/boringssl/crypto/x509/t_x509a.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include + +/* X509_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/external/boringssl/crypto/x509/vpm_int.h b/external/boringssl/crypto/x509/vpm_int.h new file mode 100644 index 0000000000..9c55defc51 --- /dev/null +++ b/external/boringssl/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 { + STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */ + unsigned int hostflags; /* Flags to control matching features */ + char *peername; /* Matching hostname in peer certificate */ + char *email; /* If not NULL email address to match */ + size_t emaillen; + unsigned char *ip; /* If not NULL IP address to match */ + size_t iplen; /* Length of IP address */ +}; diff --git a/external/boringssl/crypto/x509/x509.c b/external/boringssl/crypto/x509/x509.c new file mode 100644 index 0000000000..188fd49634 --- /dev/null +++ b/external/boringssl/crypto/x509/x509.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 + +#include +#include +#include + + +/* |X509_R_UNSUPPORTED_ALGORITHM| is no longer emitted, but continue to define + * it to avoid downstream churn. */ +OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM) + +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/external/boringssl/crypto/x509/x509_att.c b/external/boringssl/crypto/x509/x509_att.c new file mode 100644 index 0000000000..b83d32f925 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_att.c @@ -0,0 +1,375 @@ +/* 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 +#include +#include +#include +#include +#include + +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, 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, 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_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, 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_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 attr->object != NULL; +} + +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, 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, 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_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/external/boringssl/crypto/x509/x509_cmp.c b/external/boringssl/crypto/x509/x509_cmp.c new file mode 100644 index 0000000000..32862ebc9c --- /dev/null +++ b/external/boringssl/crypto/x509/x509_cmp.c @@ -0,0 +1,474 @@ +/* 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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_R_KEY_VALUES_MISMATCH); + break; + case -1: + OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + OPENSSL_PUT_ERROR(X509, 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/external/boringssl/crypto/x509/x509_d2.c b/external/boringssl/crypto/x509/x509_d2.c new file mode 100644 index 0000000000..69ae54ed8a --- /dev/null +++ b/external/boringssl/crypto/x509/x509_d2.c @@ -0,0 +1,106 @@ +/* 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 +#include + +#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/external/boringssl/crypto/x509/x509_def.c b/external/boringssl/crypto/x509/x509_def.c new file mode 100644 index 0000000000..2bf2240c35 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_def.c @@ -0,0 +1,98 @@ +/* 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 + +/* 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/external/boringssl/crypto/x509/x509_ext.c b/external/boringssl/crypto/x509/x509_ext.c new file mode 100644 index 0000000000..a329f6fab4 --- /dev/null +++ b/external/boringssl/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 +#include +#include +#include +#include +#include + +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/external/boringssl/crypto/x509/x509_lu.c b/external/boringssl/crypto/x509/x509_lu.c new file mode 100644 index 0000000000..9f427dea78 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_lu.c @@ -0,0 +1,688 @@ +/* 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 + +#include +#include +#include +#include +#include +#include + +#include "../internal.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 0; + if (ctx->skip) + return 0; + return ctx->method->get_by_subject(ctx, type, name, ret) > 0; +} + +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 0; + return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0; +} + +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 0; + return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0; +} + +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 0; + return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0; +} + +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)); + CRYPTO_MUTEX_init(&ret->objs_lock); + ret->objs = sk_X509_OBJECT_new(x509_object_cmp); + if (ret->objs == NULL) + goto err; + ret->cache = 1; + ret->get_cert_methods = sk_X509_LOOKUP_new_null(); + if (ret->get_cert_methods == NULL) + goto err; + ret->param = X509_VERIFY_PARAM_new(); + if (ret->param == NULL) + goto err; + + ret->references = 1; + return ret; + err: + if (ret) { + CRYPTO_MUTEX_cleanup(&ret->objs_lock); + 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; +} + +void X509_STORE_up_ref(X509_STORE *store) +{ + CRYPTO_refcount_inc(&store->references); +} + +static void cleanup(X509_OBJECT *a) +{ + if (a == NULL) { + return; + } + 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) +{ + size_t j; + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + + if (vfy == NULL) + return; + + if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) { + return; + } + + CRYPTO_MUTEX_cleanup(&vfy->objs_lock); + + 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); + + 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; + + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + + if (tmp == NULL || type == X509_LU_CRL) { + for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { + lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); + if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) { + tmp = &stmp; + break; + } + } + 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, ERR_R_MALLOC_FAILURE); + return 0; + } + obj->type = X509_LU_X509; + obj->data.x509 = x; + + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + + 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_R_CERT_ALREADY_IN_HASH_TABLE); + ret = 0; + } else + sk_X509_OBJECT_push(ctx->objs, obj); + + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + + 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, ERR_R_MALLOC_FAILURE); + return 0; + } + obj->type = X509_LU_CRL; + obj->data.crl = x; + + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + + 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_R_CERT_ALREADY_IN_HASH_TABLE); + ret = 0; + } else + sk_X509_OBJECT_push(ctx->objs, obj); + + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + + 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: + X509_CRL_up_ref(a->data.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; + + 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; + } + + size_t idx; + if (!sk_X509_OBJECT_find(h, &idx, &stmp)) + return -1; + + if (pnmatch != NULL) { + 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(); + if (sk == NULL) + return NULL; + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + 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_MUTEX_unlock_write(&ctx->ctx->objs_lock); + if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) { + sk_X509_free(sk); + return NULL; + } + X509_OBJECT_free_contents(&xobj); + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); + if (idx < 0) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + 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_MUTEX_unlock_write(&ctx->ctx->objs_lock); + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return NULL; + } + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + 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(); + if (sk == NULL) + return NULL; + + /* Always do lookup to possibly add new CRLs to cache. */ + 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_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); + if (idx < 0) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + 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; + X509_CRL_up_ref(x); + if (!sk_X509_CRL_push(sk, x)) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + X509_CRL_free(x); + sk_X509_CRL_pop_free(sk, X509_CRL_free); + return NULL; + } + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + 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 idx, ret; + size_t i; + xn = X509_get_issuer_name(x); + if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj)) + 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_MUTEX_lock_write(&ctx->ctx->objs_lock); + 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_MUTEX_unlock_write(&ctx->ctx->objs_lock); + 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/external/boringssl/crypto/x509/x509_obj.c b/external/boringssl/crypto/x509/x509_obj.c new file mode 100644 index 0000000000..a7f31e0325 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_obj.c @@ -0,0 +1,197 @@ +/* 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 + +#include +#include +#include +#include +#include +#include + +/* + * Limit to ensure we don't overflow: much greater than + * anything enountered in practice. + */ + +#define NAME_ONELINE_MAX (1024 * 1024) + +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; + } else if (len <= 0) { + return NULL; + } + 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; + if (num > NAME_ONELINE_MAX) { + OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); + goto end; + } + 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 (l > NAME_ONELINE_MAX) { + OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); + goto end; + } + 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, ERR_R_MALLOC_FAILURE); + end: + BUF_MEM_free(b); + return (NULL); +} diff --git a/external/boringssl/crypto/x509/x509_r2x.c b/external/boringssl/crypto/x509/x509_r2x.c new file mode 100644 index 0000000000..83951a2e78 --- /dev/null +++ b/external/boringssl/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 +#include +#include +#include +#include +#include +#include +#include + +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, 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/external/boringssl/crypto/x509/x509_req.c b/external/boringssl/crypto/x509/x509_req.c new file mode 100644 index 0000000000..69bc6f114d --- /dev/null +++ b/external/boringssl/crypto/x509/x509_req.c @@ -0,0 +1,322 @@ +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, 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); + if (pktmp == NULL) + goto err; + i = X509_REQ_set_pubkey(ret, pktmp); + EVP_PKEY_free(pktmp); + if (!i) + goto err; + + if (pkey != NULL) { + if (!X509_REQ_sign(ret, pkey, md)) + goto err; + } + return (ret); + err: + X509_REQ_free(ret); + return (NULL); +} + +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_R_KEY_VALUES_MISMATCH); + break; + case -1: + OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + if (k->type == EVP_PKEY_EC) { + OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB); + break; + } + if (k->type == EVP_PKEY_DH) { + /* No idea */ + OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY); + break; + } + OPENSSL_PUT_ERROR(X509, 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/external/boringssl/crypto/x509/x509_set.c b/external/boringssl/crypto/x509/x509_set.c new file mode 100644 index 0000000000..42e9cf0f15 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_set.c @@ -0,0 +1,149 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include + +int X509_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/external/boringssl/crypto/x509/x509_test.cc b/external/boringssl/crypto/x509/x509_test.cc new file mode 100644 index 0000000000..650163a8a5 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_test.cc @@ -0,0 +1,472 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +static const char kCrossSigningRootPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICcTCCAdqgAwIBAgIIagJHiPvE0MowDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n" +"dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowPDEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n" +"dCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwo3qFvSB9Zmlbpzn9wJp\n" +"ikI75Rxkatez8VkLqyxbOhPYl2Haz8F5p1gDG96dCI6jcLGgu3AKT9uhEQyyUko5\n" +"EKYasazSeA9CQrdyhPg0mkTYVETnPM1W/ebid1YtqQbq1CMWlq2aTDoSGAReGFKP\n" +"RTdXAbuAXzpCfi/d8LqV13UCAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgIEMB0GA1Ud\n" +"JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MBkGA1Ud\n" +"DgQSBBBHKHC7V3Z/3oLvEZx0RZRwMBsGA1UdIwQUMBKAEEcocLtXdn/egu8RnHRF\n" +"lHAwDQYJKoZIhvcNAQELBQADgYEAnglibsy6mGtpIXivtlcz4zIEnHw/lNW+r/eC\n" +"CY7evZTmOoOuC/x9SS3MF9vawt1HFUummWM6ZgErqVBOXIB4//ykrcCgf5ZbF5Hr\n" +"+3EFprKhBqYiXdD8hpBkrBoXwn85LPYWNd2TceCrx0YtLIprE2R5MB2RIq8y4Jk3\n" +"YFXvkME=\n" +"-----END CERTIFICATE-----\n"; + +static const char kRootCAPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICVTCCAb6gAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwLjEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwIBcNMTUwMTAx\n" +"MDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMC4xGjAYBgNVBAoTEUJvcmluZ1NTTCBU\n" +"RVNUSU5HMRAwDgYDVQQDEwdSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n" +"iQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM\n" +"2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw+QzGj+mz36NqhGxDWb6dstB2m8PX+plZ\n" +"w7jl81MDvUnWs8yiQ/6twgu5AbhWKZQDJKcNKCEpqa6UW0r5nwIDAQABo3oweDAO\n" +"BgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8G\n" +"A1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEEA31wH7QC+4HH5UBCeMWQEwGwYDVR0j\n" +"BBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOBgQDXylEK77Za\n" +"kKeY6ZerrScWyZhrjIGtHFu09qVpdJEzrk87k2G7iHHR9CAvSofCgEExKtWNS9dN\n" +"+9WiZp/U48iHLk7qaYXdEuO07No4BYtXn+lkOykE+FUxmA4wvOF1cTd2tdj3MzX2\n" +"kfGIBAYhzGZWhY3JbhIfTEfY1PNM1pWChQ==\n" +"-----END CERTIFICATE-----\n"; + +static const char kRootCrossSignedPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICYzCCAcygAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n" +"dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowLjEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwgZ8wDQYJKoZI\n" +"hvcNAQEBBQADgY0AMIGJAoGBAOkOfxEM5lrmhoNw9lEHLgJ4EfWyJJI47iZiAseU\n" +"8T6hd2rAj9UiaLZd4kza4IURNcKSckmNgbSIl2u3/LJEW9lNBnD5DMaP6bPfo2qE\n" +"bENZvp2y0Habw9f6mVnDuOXzUwO9SdazzKJD/q3CC7kBuFYplAMkpw0oISmprpRb\n" +"SvmfAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEFBQcD\n" +"AQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gc\n" +"flQEJ4xZATAbBgNVHSMEFDASgBBHKHC7V3Z/3oLvEZx0RZRwMA0GCSqGSIb3DQEB\n" +"CwUAA4GBAErTxYJ0en9HVRHAAr5OO5wuk5Iq3VMc79TMyQLCXVL8YH8Uk7KEwv+q\n" +"9MEKZv2eR/Vfm4HlXlUuIqfgUXbwrAYC/YVVX86Wnbpy/jc73NYVCq8FEZeO+0XU\n" +"90SWAPDdp+iL7aZdimnMtG1qlM1edmz8AKbrhN/R3IbA2CL0nCWV\n" +"-----END CERTIFICATE-----\n"; + +static const char kIntermediatePEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICXjCCAcegAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMC4xGjAYBgNV\n" +"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRAwDgYDVQQDEwdSb290IENBMCAXDTE1MDEw\n" +"MTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjA2MRowGAYDVQQKExFCb3JpbmdTU0wg\n" +"VEVTVElORzEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIGfMA0GCSqGSIb3DQEB\n" +"AQUAA4GNADCBiQKBgQC7YtI0l8ocTYJ0gKyXTtPL4iMJCNY4OcxXl48jkncVG1Hl\n" +"blicgNUa1r9m9YFtVkxvBinb8dXiUpEGhVg4awRPDcatlsBSEBuJkiZGYbRcAmSu\n" +"CmZYnf6u3aYQ18SU8WqVERPpE4cwVVs+6kwlzRw0+XDoZAczu8ZezVhCUc6NbQID\n" +"AQABo3oweDAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n" +"AQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEIwaaKi1dttdV3sfjRSy\n" +"BqMwGwYDVR0jBBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOB\n" +"gQCvnolNWEHuQS8PFVVyuLR+FKBeUUdrVbSfHSzTqNAqQGp0C9fk5oCzDq6ZgTfY\n" +"ESXM4cJhb3IAnW0UM0NFsYSKQJ50JZL2L3z5ZLQhHdbs4RmODGoC40BVdnJ4/qgB\n" +"aGSh09eQRvAVmbVCviDK2ipkWNegdyI19jFfNP5uIkGlYg==\n" +"-----END CERTIFICATE-----\n"; + +static const char kIntermediateSelfSignedPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICZjCCAc+gAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n" +"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n" +"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDYxGjAYBgNVBAoTEUJv\n" +"cmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0EwgZ8wDQYJ\n" +"KoZIhvcNAQEBBQADgY0AMIGJAoGBALti0jSXyhxNgnSArJdO08viIwkI1jg5zFeX\n" +"jyOSdxUbUeVuWJyA1RrWv2b1gW1WTG8GKdvx1eJSkQaFWDhrBE8Nxq2WwFIQG4mS\n" +"JkZhtFwCZK4KZlid/q7dphDXxJTxapURE+kThzBVWz7qTCXNHDT5cOhkBzO7xl7N\n" +"WEJRzo1tAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEF\n" +"BQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQjBpoqLV2\n" +"211Xex+NFLIGozAbBgNVHSMEFDASgBCMGmiotXbbXVd7H40UsgajMA0GCSqGSIb3\n" +"DQEBCwUAA4GBALcccSrAQ0/EqQBsx0ZDTUydHXXNP2DrUkpUKmAXIe8McqIVSlkT\n" +"6H4xz7z8VRKBo9j+drjjtCw2i0CQc8aOLxRb5WJ8eVLnaW2XRlUqAzhF0CrulfVI\n" +"E4Vs6ZLU+fra1WAuIj6qFiigRja+3YkZArG8tMA9vtlhTX/g7YBZIkqH\n" +"-----END CERTIFICATE-----\n"; + +static const char kLeafPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICXjCCAcegAwIBAgIIWjO48ufpunYwDQYJKoZIhvcNAQELBQAwNjEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAg\n" +"Fw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowMjEaMBgGA1UEChMRQm9y\n" +"aW5nU1NMIFRFU1RJTkcxFDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3\n" +"DQEBAQUAA4GNADCBiQKBgQDD0U0ZYgqShJ7oOjsyNKyVXEHqeafmk/bAoPqY/h1c\n" +"oPw2E8KmeqiUSoTPjG5IXSblOxcqpbAXgnjPzo8DI3GNMhAf8SYNYsoH7gc7Uy7j\n" +"5x8bUrisGnuTHqkqH6d4/e7ETJ7i3CpR8bvK16DggEvQTudLipz8FBHtYhFakfdh\n" +"TwIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG\n" +"CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEKN5pvbur7mlXjeMEYA0\n" +"4nUwGwYDVR0jBBQwEoAQjBpoqLV2211Xex+NFLIGozANBgkqhkiG9w0BAQsFAAOB\n" +"gQBj/p+JChp//LnXWC1k121LM/ii7hFzQzMrt70bny406SGz9jAjaPOX4S3gt38y\n" +"rhjpPukBlSzgQXFg66y6q5qp1nQTD1Cw6NkKBe9WuBlY3iYfmsf7WT8nhlT1CttU\n" +"xNCwyMX9mtdXdQicOfNjIGUCD5OLV5PgHFPRKiHHioBAhg==\n" +"-----END CERTIFICATE-----\n"; + +static const char kLeafNoKeyUsagePEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICNTCCAZ6gAwIBAgIJAIFQGaLQ0G2mMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n" +"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n" +"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDcxGjAYBgNVBAoTEUJv\n" +"cmluZ1NTTCBURVNUSU5HMRkwFwYDVQQDExBldmlsLmV4YW1wbGUuY29tMIGfMA0G\n" +"CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOKoZe75NPz77EOaMMl4/0s3PyQw++zJvp\n" +"ejHAxZiTPCJgMbEHLrSzNoHdopg+CLUH5bE4wTXM8w9Inv5P8OAFJt7gJuPUunmk\n" +"j+NoU3QfzOR6BroePcz1vXX9jyVHRs087M/sLqWRHu9IR+/A+UTcBaWaFiDVUxtJ\n" +"YOwFMwjNPQIDAQABo0gwRjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBJfLEUWHq1\n" +"27rZ1AVx2J5GMBsGA1UdIwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwDQYJKoZIhvcN\n" +"AQELBQADgYEALVKN2Y3LZJOtu6SxFIYKxbLaXhTGTdIjxipZhmbBRDFjbZjZZOTe\n" +"6Oo+VDNPYco4rBexK7umYXJyfTqoY0E8dbiImhTcGTEj7OAB3DbBomgU1AYe+t2D\n" +"uwBqh4Y3Eto+Zn4pMVsxGEfUpjzjZDel7bN1/oU/9KWPpDfywfUmjgk=\n" +"-----END CERTIFICATE-----\n"; + +static const char kForgeryPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICZzCCAdCgAwIBAgIIdTlMzQoKkeMwDQYJKoZIhvcNAQELBQAwNzEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxGTAXBgNVBAMTEGV2aWwuZXhhbXBsZS5jb20w\n" +"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDoxGjAYBgNVBAoTEUJv\n" +"cmluZ1NTTCBURVNUSU5HMRwwGgYDVQQDExNmb3JnZXJ5LmV4YW1wbGUuY29tMIGf\n" +"MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDADTwruBQZGb7Ay6s9HiYv5d1lwtEy\n" +"xQdA2Sy8Rn8uA20Q4KgqwVY7wzIZ+z5Butrsmwb70gdG1XU+yRaDeE7XVoW6jSpm\n" +"0sw35/5vJbTcL4THEFbnX0OPZnvpuZDFUkvVtq5kxpDWsVyM24G8EEq7kPih3Sa3\n" +"OMhXVXF8kso6UQIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI\n" +"KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEEYJ/WHM\n" +"8p64erPWIg4/liwwGwYDVR0jBBQwEoAQSXyxFFh6tdu62dQFcdieRjANBgkqhkiG\n" +"9w0BAQsFAAOBgQA+zH7bHPElWRWJvjxDqRexmYLn+D3Aivs8XgXQJsM94W0EzSUf\n" +"DSLfRgaQwcb2gg2xpDFoG+W0vc6O651uF23WGt5JaFFJJxqjII05IexfCNhuPmp4\n" +"4UZAXPttuJXpn74IY1tuouaM06B3vXKZR+/ityKmfJvSwxacmFcK+2ziAg==\n" +"-----END CERTIFICATE-----\n"; + +// kExamplePSSCert is an example RSA-PSS self-signed certificate, signed with +// the default hash functions. +static const char kExamplePSSCert[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICYjCCAcagAwIBAgIJAI3qUyT6SIfzMBIGCSqGSIb3DQEBCjAFogMCAWowRTEL\n" +"MAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVy\n" +"bmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDEwMDkxOTA5NTVaFw0xNTEwMDkxOTA5\n" +"NTVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQK\n" +"DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A\n" +"MIGJAoGBAPi4bIO0vNmoV8CltFl2jFQdeesiUgR+0zfrQf2D+fCmhRU0dXFahKg8\n" +"0u9aTtPel4rd/7vPCqqGkr64UOTNb4AzMHYTj8p73OxaymPHAyXvqIqDWHYg+hZ3\n" +"13mSYwFIGth7Z/FSVUlO1m5KXNd6NzYM3t2PROjCpywrta9kS2EHAgMBAAGjUDBO\n" +"MB0GA1UdDgQWBBTQQfuJQR6nrVrsNF1JEflVgXgfEzAfBgNVHSMEGDAWgBTQQfuJ\n" +"QR6nrVrsNF1JEflVgXgfEzAMBgNVHRMEBTADAQH/MBIGCSqGSIb3DQEBCjAFogMC\n" +"AWoDgYEASUy2RZcgNbNQZA0/7F+V1YTLEXwD16bm+iSVnzGwtexmQVEYIZG74K/w\n" +"xbdZQdTbpNJkp1QPjPfh0zsatw6dmt5QoZ8K8No0DjR9dgf+Wvv5WJvJUIQBoAVN\n" +"Z0IL+OQFz6+LcTHxD27JJCebrATXZA0wThGTQDm7crL+a+SujBY=\n" +"-----END CERTIFICATE-----\n"; + +// kBadPSSCertPEM is a self-signed RSA-PSS certificate with bad parameters. +static const char kBadPSSCertPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIDdjCCAjqgAwIBAgIJANcwZLyfEv7DMD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n" +"AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3jAnMSUwIwYD\n" +"VQQDDBxUZXN0IEludmFsaWQgUFNTIGNlcnRpZmljYXRlMB4XDTE1MTEwNDE2MDIz\n" +"NVoXDTE1MTIwNDE2MDIzNVowJzElMCMGA1UEAwwcVGVzdCBJbnZhbGlkIFBTUyBj\n" +"ZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTaM7WH\n" +"qVCAGAIA+zL1KWvvASTrhlq+1ePdO7wsrWX2KiYoTYrJYTnxhLnn0wrHqApt79nL\n" +"IBG7cfShyZqFHOY/IzlYPMVt+gPo293gw96Fds5JBsjhjkyGnOyr9OUntFqvxDbT\n" +"IIFU7o9IdxD4edaqjRv+fegVE+B79pDk4s0ujsk6dULtCg9Rst0ucGFo19mr+b7k\n" +"dbfn8pZ72ZNDJPueVdrUAWw9oll61UcYfk75XdrLk6JlL41GrYHc8KlfXf43gGQq\n" +"QfrpHkg4Ih2cI6Wt2nhFGAzrlcorzLliQIUJRIhM8h4IgDfpBpaPdVQLqS2pFbXa\n" +"5eQjqiyJwak2vJ8CAwEAAaNQME4wHQYDVR0OBBYEFCt180N4oGUt5LbzBwQ4Ia+2\n" +"4V97MB8GA1UdIwQYMBaAFCt180N4oGUt5LbzBwQ4Ia+24V97MAwGA1UdEwQFMAMB\n" +"Af8wMQYJKoZIhvcNAQEKMCSgDTALBglghkgBZQMEAgGhDTALBgkqhkiG9w0BAQii\n" +"BAICAN4DggEBAAjBtm90lGxgddjc4Xu/nbXXFHVs2zVcHv/mqOZoQkGB9r/BVgLb\n" +"xhHrFZ2pHGElbUYPfifdS9ztB73e1d4J+P29o0yBqfd4/wGAc/JA8qgn6AAEO/Xn\n" +"plhFeTRJQtLZVl75CkHXgUGUd3h+ADvKtcBuW9dSUncaUrgNKR8u/h/2sMG38RWY\n" +"DzBddC/66YTa3r7KkVUfW7yqRQfELiGKdcm+bjlTEMsvS+EhHup9CzbpoCx2Fx9p\n" +"NPtFY3yEObQhmL1JyoCRWqBE75GzFPbRaiux5UpEkns+i3trkGssZzsOuVqHNTNZ\n" +"lC9+9hPHIoc9UMmAQNo1vGIW3NWVoeGbaJ8=\n" +"-----END CERTIFICATE-----\n"; + +static const char kRSAKey[] = +"-----BEGIN RSA PRIVATE KEY-----\n" +"MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n" +"kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n" +"KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n" +"AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n" +"i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n" +"WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n" +"m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n" +"QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n" +"aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n" +"LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n" +"104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n" +"tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n" +"moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n" +"-----END RSA PRIVATE KEY-----\n"; + + +// CertFromPEM parses the given, NUL-terminated pem block and returns an +// |X509*|. +static ScopedX509 CertFromPEM(const char *pem) { + ScopedBIO bio(BIO_new_mem_buf(pem, strlen(pem))); + return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)); +} + +// PrivateKeyFromPEM parses the given, NUL-terminated pem block and returns an +// |EVP_PKEY*|. +static ScopedEVP_PKEY PrivateKeyFromPEM(const char *pem) { + ScopedBIO bio(BIO_new_mem_buf(const_cast(pem), strlen(pem))); + return ScopedEVP_PKEY( + PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); +} + +// CertsToStack converts a vector of |X509*| to an OpenSSL STACK_OF(X509*), +// bumping the reference counts for each certificate in question. +static STACK_OF(X509)* CertsToStack(const std::vector &certs) { + ScopedX509Stack stack(sk_X509_new_null()); + if (!stack) { + return nullptr; + } + for (auto cert : certs) { + if (!sk_X509_push(stack.get(), cert)) { + return nullptr; + } + X509_up_ref(cert); + } + + return stack.release(); +} + +static bool Verify(X509 *leaf, const std::vector &roots, + const std::vector &intermediates, + unsigned long flags = 0) { + ScopedX509Stack roots_stack(CertsToStack(roots)); + ScopedX509Stack intermediates_stack(CertsToStack(intermediates)); + if (!roots_stack || + !intermediates_stack) { + return false; + } + + ScopedX509_STORE_CTX ctx(X509_STORE_CTX_new()); + if (!ctx) { + return false; + } + if (!X509_STORE_CTX_init(ctx.get(), nullptr /* no X509_STORE */, leaf, + intermediates_stack.get())) { + return false; + } + + X509_STORE_CTX_trusted_stack(ctx.get(), roots_stack.get()); + + X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); + if (param == nullptr) { + return false; + } + X509_VERIFY_PARAM_set_time(param, 1452807555 /* Jan 14th, 2016 */); + X509_VERIFY_PARAM_set_depth(param, 16); + if (flags) { + X509_VERIFY_PARAM_set_flags(param, flags); + } + X509_STORE_CTX_set0_param(ctx.get(), param); + + ERR_clear_error(); + return X509_verify_cert(ctx.get()) == 1; +} + +static bool TestVerify() { + ScopedX509 cross_signing_root(CertFromPEM(kCrossSigningRootPEM)); + ScopedX509 root(CertFromPEM(kRootCAPEM)); + ScopedX509 root_cross_signed(CertFromPEM(kRootCrossSignedPEM)); + ScopedX509 intermediate(CertFromPEM(kIntermediatePEM)); + ScopedX509 intermediate_self_signed(CertFromPEM(kIntermediateSelfSignedPEM)); + ScopedX509 leaf(CertFromPEM(kLeafPEM)); + ScopedX509 leaf_no_key_usage(CertFromPEM(kLeafNoKeyUsagePEM)); + ScopedX509 forgery(CertFromPEM(kForgeryPEM)); + + if (!cross_signing_root || + !root || + !root_cross_signed || + !intermediate || + !intermediate_self_signed || + !leaf || + !leaf_no_key_usage || + !forgery) { + fprintf(stderr, "Failed to parse certificates\n"); + return false; + } + + std::vector empty; + if (Verify(leaf.get(), empty, empty)) { + fprintf(stderr, "Leaf verified with no roots!\n"); + return false; + } + + if (Verify(leaf.get(), empty, {intermediate.get()})) { + fprintf(stderr, "Leaf verified with no roots!\n"); + return false; + } + + if (!Verify(leaf.get(), {root.get()}, {intermediate.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Basic chain didn't verify.\n"); + return false; + } + + if (!Verify(leaf.get(), {cross_signing_root.get()}, + {intermediate.get(), root_cross_signed.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Cross-signed chain didn't verify.\n"); + return false; + } + + if (!Verify(leaf.get(), {cross_signing_root.get(), root.get()}, + {intermediate.get(), root_cross_signed.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Cross-signed chain with root didn't verify.\n"); + return false; + } + + /* This is the “altchains†test – we remove the cross-signing CA but include + * the cross-sign in the intermediates. */ + if (!Verify(leaf.get(), {root.get()}, + {intermediate.get(), root_cross_signed.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Chain with cross-sign didn't backtrack to find root.\n"); + return false; + } + + if (Verify(leaf.get(), {root.get()}, + {intermediate.get(), root_cross_signed.get()}, + X509_V_FLAG_NO_ALT_CHAINS)) { + fprintf(stderr, "Altchains test still passed when disabled.\n"); + return false; + } + + if (Verify(forgery.get(), {intermediate_self_signed.get()}, + {leaf_no_key_usage.get()})) { + fprintf(stderr, "Basic constraints weren't checked.\n"); + return false; + } + + /* Test that one cannot skip Basic Constraints checking with a contorted set + * of roots and intermediates. This is a regression test for CVE-2015-1793. */ + if (Verify(forgery.get(), + {intermediate_self_signed.get(), root_cross_signed.get()}, + {leaf_no_key_usage.get(), intermediate.get()})) { + fprintf(stderr, "Basic constraints weren't checked.\n"); + return false; + } + + return true; +} + +static bool TestPSS() { + ScopedX509 cert(CertFromPEM(kExamplePSSCert)); + if (!cert) { + return false; + } + + ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get())); + if (!pkey) { + return false; + } + + if (!X509_verify(cert.get(), pkey.get())) { + fprintf(stderr, "Could not verify certificate.\n"); + return false; + } + return true; +} + +static bool TestBadPSSParameters() { + ScopedX509 cert(CertFromPEM(kBadPSSCertPEM)); + if (!cert) { + return false; + } + + ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get())); + if (!pkey) { + return false; + } + + if (X509_verify(cert.get(), pkey.get())) { + fprintf(stderr, "Unexpectedly verified bad certificate.\n"); + return false; + } + ERR_clear_error(); + return true; +} + +static bool SignatureRoundTrips(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) { + // Make a certificate like signed with |md_ctx|'s settings.' + ScopedX509 cert(CertFromPEM(kLeafPEM)); + if (!cert || !X509_sign_ctx(cert.get(), md_ctx)) { + return false; + } + + // Ensure that |pkey| may still be used to verify the resulting signature. All + // settings in |md_ctx| must have been serialized appropriately. + return !!X509_verify(cert.get(), pkey); +} + +static bool TestSignCtx() { + ScopedEVP_PKEY pkey(PrivateKeyFromPEM(kRSAKey)); + if (!pkey) { + return false; + } + + // Test PKCS#1 v1.5. + ScopedEVP_MD_CTX md_ctx; + if (!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) || + !SignatureRoundTrips(md_ctx.get(), pkey.get())) { + fprintf(stderr, "RSA PKCS#1 with SHA-256 failed\n"); + return false; + } + + // Test RSA-PSS with custom parameters. + md_ctx.Reset(); + EVP_PKEY_CTX *pkey_ctx; + if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL, + pkey.get()) || + !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) || + !SignatureRoundTrips(md_ctx.get(), pkey.get())) { + fprintf(stderr, "RSA-PSS failed\n"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (!TestVerify() || + !TestPSS() || + !TestBadPSSParameters() || + !TestSignCtx()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/x509/x509_trs.c b/external/boringssl/crypto/x509/x509_trs.c new file mode 100644 index 0000000000..c7dfcad60e --- /dev/null +++ b/external/boringssl/crypto/x509/x509_trs.c @@ -0,0 +1,326 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include +#include +#include + +static 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_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, 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, 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, ERR_R_MALLOC_FAILURE); + trtable_free(trtmp); + return 0; + } + if (!sk_X509_TRUST_push(trtable, trtmp)) { + OPENSSL_PUT_ERROR(X509, 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/external/boringssl/crypto/x509/x509_txt.c b/external/boringssl/crypto/x509/x509_txt.c new file mode 100644 index 0000000000..17e6cdb9c2 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_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.] */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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"); + + case X509_V_ERR_INVALID_CALL: + return ("Invalid certificate verification context"); + case X509_V_ERR_STORE_LOOKUP: + return ("Issuer certificate lookup error"); + + default: + BIO_snprintf(buf, sizeof buf, "error number %ld", n); + return (buf); + } +} diff --git a/external/boringssl/crypto/x509/x509_v3.c b/external/boringssl/crypto/x509/x509_v3.c new file mode 100644 index 0000000000..ecbc0ddc0b --- /dev/null +++ b/external/boringssl/crypto/x509/x509_v3.c @@ -0,0 +1,278 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include + +int 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, 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, 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_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, 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 ex->object != NULL; +} + +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/external/boringssl/crypto/x509/x509_vfy.c b/external/boringssl/crypto/x509/x509_vfy.c new file mode 100644 index 0000000000..520408feff --- /dev/null +++ b/external/boringssl/crypto/x509/x509_vfy.c @@ -0,0 +1,2434 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vpm_int.h" +#include "../internal.h" + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = + CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; + +/* 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); + +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, *xtmp2, *chain_ss = NULL; + int bad_chain = 0; + X509_VERIFY_PARAM *param = ctx->param; + int depth, i, ok = 0; + int num, j, retry, trust; + int (*cb) (int xok, X509_STORE_CTX *xctx); + STACK_OF(X509) *sktmp = NULL; + if (ctx->cert == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + if (ctx->chain != NULL) { + /* + * This X509_STORE_CTX has already been used to verify a cert. We + * cannot do another one. + */ + OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ctx->error = X509_V_ERR_INVALID_CALL; + 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 + */ + ctx->chain = sk_X509_new_null(); + if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + 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, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto end; + } + + num = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, num - 1); + depth = param->depth; + + for (;;) { + /* If we have enough, we break */ + 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) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + /* + * If successful for now free up cert so it will be picked up + * again later. + */ + if (ok > 0) { + X509_free(xtmp); + break; + } + } + + /* If we were passed a cert chain, use it first */ + if (ctx->untrusted != NULL) { + xtmp = find_issuer(ctx, sktmp, x); + if (xtmp != NULL) { + if (!sk_X509_push(ctx->chain, xtmp)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + X509_up_ref(xtmp); + (void)sk_X509_delete_ptr(sktmp, xtmp); + ctx->last_untrusted++; + x = xtmp; + num++; + /* + * reparse the full chain for the next one + */ + continue; + } + } + break; + } + + /* Remember how many untrusted certs we have */ + j = num; + /* + * at this point, chain should contain a list of untrusted certificates. + * We now need to add at least one trusted one, if possible, otherwise we + * complain. + */ + + do { + /* + * Examine last certificate in chain and see if it is self signed. + */ + i = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, i - 1); + if (cert_self_signed(x)) { + /* we have a self signed certificate */ + if (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--; + j--; + x = sk_X509_value(ctx->chain, num - 1); + } + } + /* We now lookup certs from the certificate store */ + for (;;) { + /* If we have enough, we break */ + if (depth < num) + break; + /* If we are self signed, we break */ + if (cert_self_signed(x)) + break; + ok = ctx->get_issuer(&xtmp, ctx, x); + + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + if (ok == 0) + break; + x = xtmp; + if (!sk_X509_push(ctx->chain, x)) { + X509_free(xtmp); + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + num++; + } + + /* we now have our chain, lets check it... */ + trust = check_trust(ctx); + + /* If explicitly rejected error */ + if (trust == X509_TRUST_REJECTED) { + ok = 0; + goto end; + } + /* + * If it's not explicitly trusted then check if there is an alternative + * chain that could be used. We only do this if we haven't already + * checked via TRUSTED_FIRST and the user hasn't switched off alternate + * chain checking + */ + retry = 0; + if (trust != X509_TRUST_TRUSTED + && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) + && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { + while (j-- > 1) { + xtmp2 = sk_X509_value(ctx->chain, j - 1); + ok = ctx->get_issuer(&xtmp, ctx, xtmp2); + if (ok < 0) + goto end; + /* Check if we found an alternate chain */ + if (ok > 0) { + /* + * Free up the found cert we'll add it again later + */ + X509_free(xtmp); + + /* + * Dump all the certs above this point - we've found an + * alternate chain + */ + while (num > j) { + xtmp = sk_X509_pop(ctx->chain); + X509_free(xtmp); + num--; + } + ctx->last_untrusted = sk_X509_num(ctx->chain); + retry = 1; + break; + } + } + } + } while (retry); + + /* + * If not explicitly trusted then indicate error unless it's a single + * self signed certificate in which case we've indicated an error already + * and set bad_chain == 1 + */ + if (trust != X509_TRUST_TRUSTED && !bad_chain) { + if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { + if (ctx->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; + + /* + * 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; + + int err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, + ctx->param->flags); + if (err != X509_V_OK) { + ctx->error = err; + 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); + + end: + if (sktmp != NULL) + sk_X509_free(sktmp); + if (chain_ss != NULL) + X509_free(chain_ss); + + /* Safety net, error returns must set ctx->error */ + if (ok <= 0 && ctx->error == X509_V_OK) + ctx->error = X509_V_ERR_UNSPECIFIED; + 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); + switch (rv) { + case X509_V_OK: + continue; + case X509_V_ERR_OUT_OF_MEM: + ctx->error = rv; + return 0; + default: + ctx->error = rv; + ctx->error_depth = i; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) + return 0; + break; + } + } + } + } + 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_hosts(X509 *x, X509_VERIFY_PARAM_ID *id) +{ + size_t i; + size_t n = sk_OPENSSL_STRING_num(id->hosts); + char *name; + + if (id->peername != NULL) { + OPENSSL_free(id->peername); + id->peername = NULL; + } + for (i = 0; i < n; ++i) { + name = sk_OPENSSL_STRING_value(id->hosts, i); + if (X509_check_host(x, name, strlen(name), id->hostflags, + &id->peername) > 0) + return 1; + } + return n == 0; +} + +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->hosts && check_hosts(x, id) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) + return 0; + } + if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 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) <= 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 = 0, 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; + X509_CRL_up_ref(best_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; + X509_CRL_up_ref(delta); + *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 ((size_t)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, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + 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; + /* + * Verification errors need to be "sticky", a callback may have allowed + * an SSL handshake to continue despite an error, and we must then + * remain in an error state. Therefore, we MUST NOT clear earlier + * verification errors by setting the error to X509_V_OK. + */ + if (!ctx->verify_cb(2, ctx)) + return 0; + } + + return 1; +} + +static int check_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, remaining; + + p = buff1; + remaining = ctm->length; + str = (char *)ctm->data; + /* + * Note that the following (historical) code allows much more slack in + * the time format than RFC5280. In RFC5280, the representation is fixed: + * UTCTime: YYMMDDHHMMSSZ GeneralizedTime: YYYYMMDDHHMMSSZ + */ + if (ctm->type == V_ASN1_UTCTIME) { + /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */ + int min_length = sizeof("YYMMDDHHMMZ") - 1; + int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1; + if (remaining < min_length || remaining > max_length) + return 0; + memcpy(p, str, 10); + p += 10; + str += 10; + remaining -= 10; + } else { + /* + * YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm + */ + int min_length = sizeof("YYYYMMDDHHMMZ") - 1; + int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1; + if (remaining < min_length || remaining > max_length) + return 0; + memcpy(p, str, 12); + p += 12; + str += 12; + remaining -= 12; + } + + if ((*str == 'Z') || (*str == '-') || (*str == '+')) { + *(p++) = '0'; + *(p++) = '0'; + } else { + /* SS (seconds) */ + if (remaining < 2) + return 0; + *(p++) = *(str++); + *(p++) = *(str++); + remaining -= 2; + /* + * Skip any (up to three) fractional seconds... TODO(emilia): in + * RFC5280, fractional seconds are forbidden. Can we just kill them + * altogether? + */ + if (remaining && *str == '.') { + str++; + remaining--; + for (i = 0; i < 3 && remaining; i++, str++, remaining--) { + if (*str < '0' || *str > '9') + break; + } + } + + } + *(p++) = 'Z'; + *(p++) = '\0'; + + /* We now need either a terminating 'Z' or an offset. */ + if (!remaining) + return 0; + if (*str == 'Z') { + if (remaining != 1) + return 0; + offset = 0; + } else { + /* (+-)HHMM */ + if ((*str != '+') && (*str != '-')) + return 0; + /* + * Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. + */ + if (remaining != 5) + return 0; + if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' || + str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9') + 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); +} + +/* 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_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_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_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_R_AKID_MISMATCH); + return NULL; + } + if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) { + OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH); + return NULL; + } + /* Newer CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) { + OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER); + return NULL; + } + /* CRLs must verify */ + if (skey && (X509_CRL_verify(base, skey) <= 0 || + X509_CRL_verify(newer, skey) <= 0)) { + OPENSSL_PUT_ERROR(X509, 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, 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_unused * unused, + 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). + */ + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, + dup_func, free_func)) { + return -1; + } + return index; +} + +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) +{ + return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); +} + +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_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_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_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, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ctx, 0, sizeof(X509_STORE_CTX)); + return ctx; +} + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx) +{ + if (ctx == NULL) { + return; + } + 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; + + memset(ctx, 0, sizeof(X509_STORE_CTX)); + ctx->ctx = store; + ctx->cert = x509; + ctx->untrusted = chain; + + CRYPTO_new_ex_data(&ctx->ex_data); + + 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: + CRYPTO_free_ex_data(&g_ex_data_class, 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, 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) +{ + /* We need to be idempotent because, unfortunately, |X509_STORE_CTX_free| + * also calls this function. */ + if (ctx->cleanup != NULL) { + ctx->cleanup(ctx); + ctx->cleanup = NULL; + } + 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(&g_ex_data_class, 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/external/boringssl/crypto/x509/x509_vpm.c b/external/boringssl/crypto/x509/x509_vpm.c new file mode 100644 index 0000000000..02a589888f --- /dev/null +++ b/external/boringssl/crypto/x509/x509_vpm.c @@ -0,0 +1,636 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "vpm_int.h" + +/* X509_VERIFY_PARAM functions */ + +#define SET_HOST 0 +#define ADD_HOST 1 + +static char *str_copy(char *s) +{ + return OPENSSL_strdup(s); +} + +static void str_free(char *s) +{ + OPENSSL_free(s); +} + +#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free) + +static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, + const char *name, size_t namelen) +{ + char *copy; + + /* + * Refuse names with embedded NUL bytes. + * XXX: Do we need to push an error onto the error stack? + */ + if (name && memchr(name, '\0', namelen)) + return 0; + + if (mode == SET_HOST && id->hosts) { + string_stack_free(id->hosts); + id->hosts = NULL; + } + if (name == NULL) + return 1; + + copy = BUF_strndup(name, namelen); + if (copy == NULL) + return 0; + + if (id->hosts == NULL && + (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { + OPENSSL_free(copy); + return 0; + } + + if (!sk_OPENSSL_STRING_push(id->hosts, copy)) { + OPENSSL_free(copy); + if (sk_OPENSSL_STRING_num(id->hosts) == 0) { + sk_OPENSSL_STRING_free(id->hosts); + id->hosts = NULL; + } + return 0; + } + + return 1; +} + +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->hosts) { + string_stack_free(paramid->hosts); + paramid->hosts = NULL; + } + if (paramid->peername) { + OPENSSL_free(paramid->peername); + paramid->peername = NULL; + } + 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) +{ + if (param == NULL) + return; + 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; + } + + /* Copy the host flags if and only if we're copying the host list */ + if (test_x509_verify_param_copy_id(hosts, NULL)) { + if (dest->id->hosts) { + string_stack_free(dest->id->hosts); + dest->id->hosts = NULL; + } + if (id->hosts) { + dest->id->hosts = + sk_OPENSSL_STRING_deep_copy(id->hosts, str_copy, str_free); + if (dest->id->hosts == NULL) + 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(char **pdest, size_t *pdestlen, + const char *src, size_t srclen) +{ + void *tmp; + if (src) { + if (srclen == 0) { + tmp = BUF_strdup(src); + srclen = strlen(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(¶m->purpose, purpose); +} + +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) +{ + return X509_TRUST_set(¶m->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 char *name, size_t namelen) +{ + return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen); +} + +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen); +} + +void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags) +{ + param->id->hostflags = flags; +} + +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) +{ + return param->id->peername; +} + +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, size_t emaillen) +{ + return int_x509_param_set1(¶m->id->email, ¶m->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((char **)¶m->id->ip, ¶m->id->iplen, + (char *)ip, iplen); +} + +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) +{ + unsigned char ipout[16]; + size_t iplen; + + iplen = (size_t)a2i_ipadd(ipout, ipasc); + if (iplen == 0) + return 0; + return X509_VERIFY_PARAM_set1_ip(param, ipout, 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, 0U, NULL, 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/external/boringssl/crypto/x509/x509cset.c b/external/boringssl/crypto/x509/x509cset.c new file mode 100644 index 0000000000..a292710ee8 --- /dev/null +++ b/external/boringssl/crypto/x509/x509cset.c @@ -0,0 +1,169 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include +#include + +#include "../internal.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; +} + +void X509_CRL_up_ref(X509_CRL *crl) +{ + CRYPTO_refcount_inc(&crl->references); +} + +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/external/boringssl/crypto/x509/x509name.c b/external/boringssl/crypto/x509/x509name.c new file mode 100644 index 0000000000..050e16a84e --- /dev/null +++ b/external/boringssl/crypto/x509/x509name.c @@ -0,0 +1,386 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include + +int 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, 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_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 = OBJ_nid2obj(nid); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); + return NULL; + } + return X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); +} + +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, 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/external/boringssl/crypto/x509/x509rset.c b/external/boringssl/crypto/x509/x509rset.c new file mode 100644 index 0000000000..c4e6683dea --- /dev/null +++ b/external/boringssl/crypto/x509/x509rset.c @@ -0,0 +1,81 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + +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/external/boringssl/crypto/x509/x509spki.c b/external/boringssl/crypto/x509/x509spki.c new file mode 100644 index 0000000000..4a9b95e769 --- /dev/null +++ b/external/boringssl/crypto/x509/x509spki.c @@ -0,0 +1,137 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->spkac == NULL)) + return (0); + return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey)); +} + +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, X509_R_BASE64_DECODE_ERROR); + return NULL; + } + if (!(spki_der = OPENSSL_malloc(spki_len))) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!EVP_DecodeBase64 + (spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) { + OPENSSL_PUT_ERROR(X509, 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, ERR_R_OVERFLOW); + return NULL; + } + der_spki = OPENSSL_malloc(der_len); + if (der_spki == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + b64_str = OPENSSL_malloc(b64_len); + if (b64_str == NULL) { + OPENSSL_free(der_spki); + OPENSSL_PUT_ERROR(X509, 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/external/boringssl/crypto/x509/x509type.c b/external/boringssl/crypto/x509/x509type.c new file mode 100644 index 0000000000..d4f5a4dc35 --- /dev/null +++ b/external/boringssl/crypto/x509/x509type.c @@ -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.] */ + +#include +#include +#include + +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/external/boringssl/crypto/x509/x_algor.c b/external/boringssl/crypto/x509/x_algor.c new file mode 100644 index 0000000000..abacd061df --- /dev/null +++ b/external/boringssl/crypto/x509/x_algor.c @@ -0,0 +1,151 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + + +ASN1_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/external/boringssl/crypto/x509/x_all.c b/external/boringssl/crypto/x509/x_all.c new file mode 100644 index 0000000000..c430a7d31e --- /dev/null +++ b/external/boringssl/crypto/x509/x_all.c @@ -0,0 +1,501 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} + +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); +} + +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)); +} + +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *x, EVP_PKEY *pkey) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, + x->signature, x->spkac, pkey)); +} + +#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); +} + +#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_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa); +} + +int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa) +{ + return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa); +} + +RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) +{ + return ASN1_d2i_fp_of(RSA, RSA_new, d2i_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_i2d_fp_of_const(RSA, i2d_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_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa); +} + +int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa) +{ + return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa); +} + +RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) +{ + return ASN1_d2i_bio_of(RSA, RSA_new, d2i_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_i2d_bio_of_const(RSA, i2d_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)); +} + +#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/external/boringssl/crypto/x509/x_attrib.c b/external/boringssl/crypto/x509/x_attrib.c new file mode 100644 index 0000000000..de8c95cc1c --- /dev/null +++ b/external/boringssl/crypto/x509/x_attrib.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + +/* + * X509_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/external/boringssl/crypto/x509/x_crl.c b/external/boringssl/crypto/x509/x_crl.c new file mode 100644 index 0000000000..934571dd54 --- /dev/null +++ b/external/boringssl/crypto/x509/x_crl.c @@ -0,0 +1,539 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.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) = { + 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, 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 struct CRYPTO_STATIC_MUTEX g_crl_sort_lock = CRYPTO_STATIC_MUTEX_INIT; + +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. + */ + + CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock); + const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked); + CRYPTO_STATIC_MUTEX_unlock_read(&g_crl_sort_lock); + + if (!is_sorted) { + CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock); + if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) { + sk_X509_REVOKED_sort(crl->crl->revoked); + } + CRYPTO_STATIC_MUTEX_unlock_write(&g_crl_sort_lock); + } + + 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/external/boringssl/crypto/x509/x_exten.c b/external/boringssl/crypto/x509/x_exten.c new file mode 100644 index 0000000000..36403e4884 --- /dev/null +++ b/external/boringssl/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 +#include +#include +#include + + +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/external/boringssl/crypto/x509/x_info.c b/external/boringssl/crypto/x509/x_info.c new file mode 100644 index 0000000000..177cd0eb58 --- /dev/null +++ b/external/boringssl/crypto/x509/x_info.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include + +X509_INFO *X509_INFO_new(void) +{ + X509_INFO *ret = NULL; + + ret = (X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (NULL); + } + + ret->enc_cipher.cipher = NULL; + ret->enc_len = 0; + ret->enc_data = NULL; + + ret->x509 = NULL; + ret->crl = NULL; + ret->x_pkey = NULL; + return (ret); +} + +void X509_INFO_free(X509_INFO *x) +{ + if (x == NULL) + return; + + 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/external/boringssl/crypto/x509/x_name.c b/external/boringssl/crypto/x509/x_name.c new file mode 100644 index 0000000000..d7dbf80464 --- /dev/null +++ b/external/boringssl/crypto/x509/x_name.c @@ -0,0 +1,534 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../asn1/asn1_locl.h" + +typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; +DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY) + +/* + * Maximum length of X509_NAME: much larger than anything we should + * ever see in practice. + */ + +#define X509_NAME_MAX (1024 * 1024) + +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); + +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. + */ + +static 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, + NULL, +}; + +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, 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 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_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; + /* Bound the size of an X509_NAME we are willing to parse. */ + if (len > X509_NAME_MAX) { + len = X509_NAME_MAX; + } + 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); + /* We've decoded it: now cache encoding */ + if (!x509_name_ex_new(&nm.a, NULL) || !BUF_MEM_grow(nm.x->bytes, p - q)) { + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_pop_free); + 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, 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 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, ERR_R_MALLOC_FAILURE); + return -1; +} + +/* + * 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; + + /* Ignore trailing spaces */ + while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) { + 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/external/boringssl/crypto/x509/x_pkey.c b/external/boringssl/crypto/x509/x_pkey.c new file mode 100644 index 0000000000..fc445954e6 --- /dev/null +++ b/external/boringssl/crypto/x509/x_pkey.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 + +#include + +#include +#include +#include +#include + +X509_PKEY *X509_PKEY_new(void) +{ + X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + memset(ret, 0, sizeof(X509_PKEY)); + + 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) +{ + if (x == NULL) + 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/external/boringssl/crypto/x509/x_pubkey.c b/external/boringssl/crypto/x509/x_pubkey.c new file mode 100644 index 0000000000..23534b2bfe --- /dev/null +++ b/external/boringssl/crypto/x509/x_pubkey.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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../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; + uint8_t *spki = NULL; + size_t spki_len; + + if (x == NULL) + return (0); + + CBB cbb; + if (!CBB_init(&cbb, 0) || + !EVP_marshal_public_key(&cbb, pkey) || + !CBB_finish(&cbb, &spki, &spki_len) || + spki_len > LONG_MAX) { + CBB_cleanup(&cbb); + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR); + goto error; + } + + const uint8_t *p = spki; + pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len); + if (pk == NULL || p != spki + spki_len) { + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + + OPENSSL_free(spki); + X509_PUBKEY_free(*x); + *x = pk; + + return 1; + error: + X509_PUBKEY_free(pk); + OPENSSL_free(spki); + return 0; +} + +/* g_pubkey_lock is used to protect the initialisation of the |pkey| member of + * |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t| + * inside it for this, but |CRYPTO_once_t| is private and |X509_PUBKEY| is + * not. */ +static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT; + +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) +{ + EVP_PKEY *ret = NULL; + uint8_t *spki = NULL; + + if (key == NULL) + goto error; + + CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock); + if (key->pkey != NULL) { + CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); + return EVP_PKEY_up_ref(key->pkey); + } + CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); + + /* Re-encode the |X509_PUBKEY| to DER and parse it. */ + int spki_len = i2d_X509_PUBKEY(key, &spki); + if (spki_len < 0) { + goto error; + } + CBS cbs; + CBS_init(&cbs, spki, (size_t)spki_len); + ret = EVP_parse_public_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + + /* Check to see if another thread set key->pkey first */ + CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock); + if (key->pkey) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); + EVP_PKEY_free(ret); + ret = key->pkey; + } else { + key->pkey = ret; + CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); + } + + OPENSSL_free(spki); + return EVP_PKEY_up_ref(ret); + + error: + OPENSSL_free(spki); + 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, 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, 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, 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/external/boringssl/crypto/x509/x_req.c b/external/boringssl/crypto/x509/x_req.c new file mode 100644 index 0000000000..5dfe19e5d8 --- /dev/null +++ b/external/boringssl/crypto/x509/x_req.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 + +#include +#include +#include + +/* + * 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) = { + 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/external/boringssl/crypto/x509/x_sig.c b/external/boringssl/crypto/x509/x_sig.c new file mode 100644 index 0000000000..e18024a72c --- /dev/null +++ b/external/boringssl/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 + +#include +#include + + +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/external/boringssl/crypto/x509/x_spki.c b/external/boringssl/crypto/x509/x_spki.c new file mode 100644 index 0000000000..86da6ddf1b --- /dev/null +++ b/external/boringssl/crypto/x509/x_spki.c @@ -0,0 +1,80 @@ +/* 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 who wrote it. + * It is under my Copyright with his permission. + */ + +#include +#include + + +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/external/boringssl/crypto/x509/x_val.c b/external/boringssl/crypto/x509/x_val.c new file mode 100644 index 0000000000..ad4f7e140a --- /dev/null +++ b/external/boringssl/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 + +#include +#include + + +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/external/boringssl/crypto/x509/x_x509.c b/external/boringssl/crypto/x509/x_x509.c new file mode 100644 index 0000000000..e21258d4fa --- /dev/null +++ b/external/boringssl/crypto/x509/x_x509.c @@ -0,0 +1,290 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +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(&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(&g_ex_data_class, 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) = { + 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_refcount_inc(&x->references); + return x; +} + +int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused * unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) +{ + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, + dup_func, free_func)) { + return -1; + } + return index; +} + +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 = *pp; + X509 *ret; + int freeret = 0; + + if (!a || *a == NULL) + freeret = 1; + ret = d2i_X509(a, &q, length); + /* If certificate unreadable then forget it */ + if (!ret) + return NULL; + /* update length */ + length -= q - *pp; + /* Parse auxiliary information if there is any. */ + if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) + goto err; + *pp = q; + return ret; + err: + if (freeret) { + X509_free(ret); + if (a) + *a = NULL; + } + return NULL; +} + +/* + * Serialize trusted certificate to *pp or just return the required buffer + * length if pp == NULL. We ultimately want to avoid modifying *pp in the + * error path, but that depends on similar hygiene in lower-level functions. + * Here we avoid compounding the problem. + */ +static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) +{ + int length, tmplen; + unsigned char *start = pp != NULL ? *pp : NULL; + + assert(pp == NULL || *pp != NULL); + + /* + * This might perturb *pp on error, but fixing that belongs in i2d_X509() + * not here. It should be that if a == NULL length is zero, but we check + * both just in case. + */ + length = i2d_X509(a, pp); + if (length <= 0 || a == NULL) { + return length; + } + + tmplen = i2d_X509_CERT_AUX(a->aux, pp); + if (tmplen < 0) { + if (start != NULL) + *pp = start; + return tmplen; + } + length += tmplen; + + return length; +} + +/* + * Serialize trusted certificate to *pp, or just return the required buffer + * length if pp == NULL. + * + * When pp is not NULL, but *pp == NULL, we allocate the buffer, but since + * we're writing two ASN.1 objects back to back, we can't have i2d_X509() do + * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the + * allocated buffer. + */ +int i2d_X509_AUX(X509 *a, unsigned char **pp) +{ + int length; + unsigned char *tmp; + + /* Buffer provided by caller */ + if (pp == NULL || *pp != NULL) + return i2d_x509_aux_internal(a, pp); + + /* Obtain the combined length */ + if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) + return length; + + /* Allocate requisite combined storage */ + *pp = tmp = OPENSSL_malloc(length); + if (tmp == NULL) + return -1; /* Push error onto error stack? */ + + /* Encode, but keep *pp at the originally malloced pointer */ + length = i2d_x509_aux_internal(a, &tmp); + if (length <= 0) { + OPENSSL_free(*pp); + *pp = NULL; + } + 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/external/boringssl/crypto/x509/x_x509a.c b/external/boringssl/crypto/x509/x_x509a.c new file mode 100644 index 0000000000..a63ee42241 --- /dev/null +++ b/external/boringssl/crypto/x509/x_x509a.c @@ -0,0 +1,205 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +/* + * X509_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) +{ + ASN1_OBJECT *objtmp = OBJ_dup(obj); + if (objtmp == NULL) + goto err; + X509_CERT_AUX *aux = aux_get(x); + if (aux->trust == NULL) { + aux->trust = sk_ASN1_OBJECT_new_null(); + if (aux->trust == NULL) + goto err; + } + if (!sk_ASN1_OBJECT_push(aux->trust, objtmp)) + goto err; + return 1; + + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj) +{ + ASN1_OBJECT *objtmp = OBJ_dup(obj); + if (objtmp == NULL) + goto err; + X509_CERT_AUX *aux = aux_get(x); + if (aux->reject == NULL) { + aux->reject = sk_ASN1_OBJECT_new_null(); + if (aux->reject == NULL) + goto err; + } + if (!sk_ASN1_OBJECT_push(aux->reject, objtmp)) + goto err; + return 1; + + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +void X509_trust_clear(X509 *x) +{ + if (x->aux && x->aux->trust) { + sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free); + x->aux->trust = NULL; + } +} + +void X509_reject_clear(X509 *x) +{ + if (x->aux && x->aux->reject) { + sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free); + x->aux->reject = NULL; + } +} + +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/external/boringssl/crypto/x509v3/CMakeLists.txt b/external/boringssl/crypto/x509v3/CMakeLists.txt new file mode 100644 index 0000000000..fb5b76b9aa --- /dev/null +++ b/external/boringssl/crypto/x509v3/CMakeLists.txt @@ -0,0 +1,68 @@ +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 +) + +if(ENABLE_TESTS) +add_executable( + v3name_test + + v3name_test.c + + $ +) + +target_link_libraries(v3name_test crypto) +add_dependencies(all_tests v3name_test) + +add_executable( + tab_test + + tab_test.c + + $ +) + +target_link_libraries(tab_test crypto) +add_dependencies(all_tests tab_test) +endif() diff --git a/external/boringssl/crypto/x509v3/ext_dat.h b/external/boringssl/crypto/x509v3/ext_dat.h new file mode 100644 index 0000000000..9ece19c50d --- /dev/null +++ b/external/boringssl/crypto/x509v3/ext_dat.h @@ -0,0 +1,135 @@ +/* + * 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 const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; +extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, + v3_sinfo; +extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, + v3_akey_id; +extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate; +extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, + v3_freshest_crl; +extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, + v3_ocsp_acutoff; +extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, + v3_ocsp_serviceloc; +extern const X509V3_EXT_METHOD v3_crl_hold, v3_pci; +extern const X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints; +extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp; +extern const X509V3_EXT_METHOD v3_addr, v3_asid; + +/* + * 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/external/boringssl/crypto/x509v3/pcy_cache.c b/external/boringssl/crypto/x509v3/pcy_cache.c new file mode 100644 index 0000000000..b8a4be2740 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_cache.c @@ -0,0 +1,284 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include +#include +#include + +#include "pcy_int.h" +#include "../internal.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); +} + +/* + * g_x509_policy_cache_lock is used to protect against concurrent calls to + * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t| in + * the |X509| structure, but |CRYPTO_once_t| isn't public. + */ +static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock = + CRYPTO_STATIC_MUTEX_INIT; + +const X509_POLICY_CACHE *policy_cache_set(X509 *x) +{ + X509_POLICY_CACHE *cache; + + CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock); + cache = x->policy_cache; + CRYPTO_STATIC_MUTEX_unlock_read(&g_x509_policy_cache_lock); + + if (cache != NULL) + return cache; + + CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock); + if (x->policy_cache == NULL) + policy_cache_new(x); + cache = x->policy_cache; + CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_policy_cache_lock); + + return 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/external/boringssl/crypto/x509v3/pcy_data.c b/external/boringssl/crypto/x509v3/pcy_data.c new file mode 100644 index 0000000000..498de4dd13 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_data.c @@ -0,0 +1,130 @@ +/* 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 +#include +#include +#include + +#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/external/boringssl/crypto/x509v3/pcy_int.h b/external/boringssl/crypto/x509v3/pcy_int.h new file mode 100644 index 0000000000..b5075f9edb --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_int.h @@ -0,0 +1,217 @@ +/* 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/external/boringssl/crypto/x509v3/pcy_lib.c b/external/boringssl/crypto/x509v3/pcy_lib.c new file mode 100644 index 0000000000..764f38f914 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_lib.c @@ -0,0 +1,164 @@ +/* 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 +#include + +#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/external/boringssl/crypto/x509v3/pcy_map.c b/external/boringssl/crypto/x509v3/pcy_map.c new file mode 100644 index 0000000000..7263c69200 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_map.c @@ -0,0 +1,130 @@ +/* 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 +#include +#include + +#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/external/boringssl/crypto/x509v3/pcy_node.c b/external/boringssl/crypto/x509v3/pcy_node.c new file mode 100644 index 0000000000..cf4e79d8b0 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_node.c @@ -0,0 +1,188 @@ +/* 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 +#include +#include +#include +#include + +#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/external/boringssl/crypto/x509v3/pcy_tree.c b/external/boringssl/crypto/x509v3/pcy_tree.c new file mode 100644 index 0000000000..e7484e52c6 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_tree.c @@ -0,0 +1,828 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "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 ((size_t)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/external/boringssl/crypto/x509v3/tab_test.c b/external/boringssl/crypto/x509v3/tab_test.c new file mode 100644 index 0000000000..19005474e8 --- /dev/null +++ b/external/boringssl/crypto/x509v3/tab_test.c @@ -0,0 +1,108 @@ +/* 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 + +#include +#include +#include +#include + +#if !defined(BORINGSSL_SHARED_LIBRARY) +# include "ext_dat.h" +#endif + +int main(void) +{ +#if !defined(BORINGSSL_SHARED_LIBRARY) + unsigned i; + int 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; + } +#else + /* TODO(davidben): Fix this test in the shared library build. */ + printf("PASS\n"); + return 0; +#endif +} diff --git a/external/boringssl/crypto/x509v3/v3_akey.c b/external/boringssl/crypto/x509v3/v3_akey.c new file mode 100644 index 0000000000..4503e6155f --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_akey.c @@ -0,0 +1,204 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, + STACK_OF(CONF_VALUE) + *extlist); +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_akey_id = { + 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, 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, 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, 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, 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, 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/external/boringssl/crypto/x509v3/v3_akeya.c b/external/boringssl/crypto/x509v3/v3_akeya.c new file mode 100644 index 0000000000..844dee529f --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_akeya.c @@ -0,0 +1,72 @@ +/* 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 + +#include +#include +#include +#include + + +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/external/boringssl/crypto/x509v3/v3_alt.c b/external/boringssl/crypto/x509v3/v3_alt.c new file mode 100644 index 0000000000..152bd79f85 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_alt.c @@ -0,0 +1,614 @@ +/* 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 +#include + +#include +#include +#include +#include +#include + +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", "", &ret); + break; + + case GEN_X400: + X509V3_add_value("X400Name", "", &ret); + break; + + case GEN_EDIPARTY: + X509V3_add_value("EdiPartyName", "", &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", "", &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:"); + break; + + case GEN_X400: + BIO_printf(out, "X400Name:"); + break; + + case GEN_EDIPARTY: + /* Maybe fix this: it is supported now */ + BIO_printf(out, "EdiPartyName:"); + break; + + case GEN_EMAIL: + BIO_printf(out, "email:%s", gen->d.ia5->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:"); + 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, X509V3_R_MISSING_VALUE); + return NULL; + } + + if (out) + gen = out; + else { + gen = GENERAL_NAME_new(); + if (gen == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + + switch (gen_type) { + case GEN_URI: + case GEN_EMAIL: + case GEN_DNS: + is_string = 1; + break; + + case GEN_RID: + { + ASN1_OBJECT *obj; + if (!(obj = OBJ_txt2obj(value, 0))) { + OPENSSL_PUT_ERROR(X509V3, 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, 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, X509V3_R_DIRNAME_ERROR); + goto err; + } + break; + + case GEN_OTHERNAME: + if (!do_othername(gen, value, ctx)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR); + goto err; + } + break; + default: + OPENSSL_PUT_ERROR(X509V3, 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, 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, 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, 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); + if (objtmp == NULL) + return 0; + 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 = 0; + STACK_OF(CONF_VALUE) *sk = NULL; + X509_NAME *nm = X509_NAME_new(); + if (nm == NULL) + goto err; + sk = X509V3_get_section(ctx, value); + if (sk == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); + ERR_add_error_data(2, "section=", value); + goto err; + } + /* FIXME: should allow other character types... */ + if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) + goto err; + gen->d.dirn = nm; + ret = 1; + + err: + if (!ret) + X509_NAME_free(nm); + X509V3_section_free(ctx, sk); + return ret; +} diff --git a/external/boringssl/crypto/x509v3/v3_bcons.c b/external/boringssl/crypto/x509v3/v3_bcons.c new file mode 100644 index 0000000000..aefefdff77 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_bcons.c @@ -0,0 +1,133 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) + *extlist); +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_bcons = { + 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, 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, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + return bcons; + err: + BASIC_CONSTRAINTS_free(bcons); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_bitst.c b/external/boringssl/crypto/x509v3/v3_bitst.c new file mode 100644 index 0000000000..86a8c3615b --- /dev/null +++ b/external/boringssl/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 +#include + +#include +#include +#include +#include + +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, 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, ERR_R_MALLOC_FAILURE); + M_ASN1_BIT_STRING_free(bs); + return NULL; + } + break; + } + } + if (!bnam->lname) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); + X509V3_conf_err(val); + M_ASN1_BIT_STRING_free(bs); + return NULL; + } + } + return bs; +} diff --git a/external/boringssl/crypto/x509v3/v3_conf.c b/external/boringssl/crypto/x509v3/v3_conf.c new file mode 100644 index 0000000000..66abca4e93 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_conf.c @@ -0,0 +1,460 @@ +/* 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../internal.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_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, X509V3_R_UNKNOWN_EXTENSION_NAME); + return NULL; + } + if (!(method = X509V3_EXT_get_nid(ext_nid))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + /* Now get internal extension representation based on type */ + if (method->v2i) { + if (*value == '@') + nval = NCONF_get_section(conf, value + 1); + else + nval = X509V3_parse_list(value); + if (sk_CONF_VALUE_num(nval) <= 0) { + OPENSSL_PUT_ERROR(X509V3, 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, X509V3_R_NO_CONFIG_DATABASE); + return NULL; + } + if (!(ext_struc = method->r2i(method, ctx, value))) + return NULL; + } else { + OPENSSL_PUT_ERROR(X509V3, 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, 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_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 = 0; + ASN1_OBJECT *obj = NULL; + ASN1_OCTET_STRING *oct = NULL; + X509_EXTENSION *extension = NULL; + if (!(obj = OBJ_txt2obj(ext, 0))) { + OPENSSL_PUT_ERROR(X509V3, 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, 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, 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_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_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; +} diff --git a/external/boringssl/crypto/x509v3/v3_cpols.c b/external/boringssl/crypto/x509v3/v3_cpols.c new file mode 100644 index 0000000000..d67dcb08e7 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_cpols.c @@ -0,0 +1,496 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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, ERR_R_MALLOC_FAILURE); + return NULL; + } + vals = X509V3_parse_list(value); + if (vals == NULL) { + OPENSSL_PUT_ERROR(X509V3, 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, 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, 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, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol = POLICYINFO_new(); + if (pol == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ASN1_OBJECT_free(pobj); + goto err; + } + pol->policyid = pobj; + } + if (!sk_POLICYINFO_push(pols, pol)) { + POLICYINFO_free(pol); + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pols; + err: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + sk_POLICYINFO_pop_free(pols, POLICYINFO_free); + return NULL; +} + +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org) +{ + 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, 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); + if (qual->pqualid == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); + goto err; + } + qual->d.cpsuri = M_ASN1_IA5STRING_new(); + if (qual->d.cpsuri == NULL) { + goto err; + } + 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, 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, 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, X509V3_R_INVALID_OPTION); + + X509V3_conf_err(cnf); + goto err; + } + } + if (!pol->policyid) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER); + goto err; + } + + return pol; + + merr: + OPENSSL_PUT_ERROR(X509V3, 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 (qual->pqualid == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); + goto err; + } + 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 (not->exptext == NULL) + goto merr; + if (!ASN1_STRING_set(not->exptext, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!strcmp(cnf->name, "organization")) { + NOTICEREF *nref; + if (!not->noticeref) { + if (!(nref = NOTICEREF_new())) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + if (ia5org) + nref->organization->type = V_ASN1_IA5STRING; + else + nref->organization->type = V_ASN1_VISIBLESTRING; + if (!ASN1_STRING_set(nref->organization, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!strcmp(cnf->name, "noticeNumbers")) { + NOTICEREF *nref; + STACK_OF(CONF_VALUE) *nos; + if (!not->noticeref) { + if (!(nref = NOTICEREF_new())) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + nos = X509V3_parse_list(cnf->value); + if (!nos || !sk_CONF_VALUE_num(nos)) { + OPENSSL_PUT_ERROR(X509V3, 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, X509V3_R_INVALID_OPTION); + X509V3_conf_err(cnf); + goto err; + } + } + + if (not->noticeref && + (!not->noticeref->noticenos || !not->noticeref->organization)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); + goto err; + } + + return qual; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + + err: + POLICYQUALINFO_free(qual); + return NULL; +} + +static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) +{ + CONF_VALUE *cnf; + ASN1_INTEGER *aint; + + 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, X509V3_R_INVALID_NUMBER); + goto err; + } + if (!sk_ASN1_INTEGER_push(nnums, aint)) + goto merr; + } + return 1; + + merr: + OPENSSL_PUT_ERROR(X509V3, 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/external/boringssl/crypto/x509v3/v3_crld.c b/external/boringssl/crypto/x509v3/v3_crld.c new file mode 100644 index 0000000000..c93c44955d --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_crld.c @@ -0,0 +1,561 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +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, 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, 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, X509V3_R_INVALID_MULTIPLE_RDNS); + goto err; + } + } else + return 0; + + if (*pdp) { + OPENSSL_PUT_ERROR(X509V3, 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, "\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, 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, X509V3_R_INVALID_NAME); + X509V3_conf_err(cnf); + goto err; + } + } + return idp; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + err: + ISSUING_DIST_POINT_free(idp); + return NULL; +} + +static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) +{ + 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\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/external/boringssl/crypto/x509v3/v3_enum.c b/external/boringssl/crypto/x509v3/v3_enum.c new file mode 100644 index 0000000000..6bfb232c5c --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_enum.c @@ -0,0 +1,100 @@ +/* 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 + +#include +#include +#include + +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/external/boringssl/crypto/x509v3/v3_extku.c b/external/boringssl/crypto/x509v3/v3_extku.c new file mode 100644 index 0000000000..952e032c21 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_extku.c @@ -0,0 +1,148 @@ +/* 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 + +#include +#include +#include +#include +#include + +static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD + *method, void *eku, STACK_OF(CONF_VALUE) + *extlist); + +const X509V3_EXT_METHOD v3_ext_ku = { + 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, 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, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + sk_ASN1_OBJECT_push(extku, objtmp); + } + return extku; +} diff --git a/external/boringssl/crypto/x509v3/v3_genn.c b/external/boringssl/crypto/x509v3/v3_genn.c new file mode 100644 index 0000000000..2331cd490d --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_genn.c @@ -0,0 +1,250 @@ +/* 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 + +#include +#include +#include +#include + + +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/external/boringssl/crypto/x509v3/v3_ia5.c b/external/boringssl/crypto/x509v3/v3_ia5.c new file mode 100644 index 0000000000..6fc6b59b5c --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_ia5.c @@ -0,0 +1,119 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include + +static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + ASN1_IA5STRING *ia5); +static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); +const X509V3_EXT_METHOD v3_ns_ia5_list[] = { + EXT_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, 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, 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, ERR_R_MALLOC_FAILURE); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_info.c b/external/boringssl/crypto/x509v3/v3_info.c new file mode 100644 index 0000000000..482208d7c0 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_info.c @@ -0,0 +1,212 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, AUTHORITY_INFO_ACCESS + *ainfo, STACK_OF(CONF_VALUE) + *ret); +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) + *nval); + +const X509V3_EXT_METHOD v3_info = { 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, 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, 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, ERR_R_MALLOC_FAILURE); + goto err; + } + ptmp = strchr(cnf->name, ';'); + if (!ptmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX); + goto err; + } + objlen = ptmp - cnf->name; + ctmp.name = ptmp + 1; + ctmp.value = cnf->value; + if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) + goto err; + if (!(objtmp = OPENSSL_malloc(objlen + 1))) { + OPENSSL_PUT_ERROR(X509V3, 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, 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/external/boringssl/crypto/x509v3/v3_int.c b/external/boringssl/crypto/x509v3/v3_int.c new file mode 100644 index 0000000000..7bde446c28 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_int.c @@ -0,0 +1,91 @@ +/* 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 + +#include +#include + +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/external/boringssl/crypto/x509v3/v3_lib.c b/external/boringssl/crypto/x509v3/v3_lib.c new file mode 100644 index 0000000000..c4718e33bb --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_lib.c @@ -0,0 +1,362 @@ +/* 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 + +#include +#include +#include +#include +#include + +#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, ERR_R_MALLOC_FAILURE); + ext_list_free(ext); + return 0; + } + if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { + OPENSSL_PUT_ERROR(X509V3, 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_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_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_R_EXTENSION_NOT_FOUND); + return 0; + } + if (! + (tmpext = + (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return 0; + } + *tmpext = *ext; + tmpext->ext_nid = nid_to; + tmpext->ext_flags |= X509V3_EXT_DYNAMIC; + return X509V3_EXT_add(tmpext); +} + +void X509V3_EXT_cleanup(void) +{ + sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free); + ext_list = NULL; +} + +static void ext_list_free(X509V3_EXT_METHOD *ext) +{ + if (ext->ext_flags & X509V3_EXT_DYNAMIC) + OPENSSL_free(ext); +} + +/* + * Legacy function: we don't need to add standard extensions any more because + * they are now kept in ext_dat.h. + */ + +int X509V3_add_standard_extensions(void) +{ + return 1; +} + +/* Return an extension internal structure */ + +void *X509V3_EXT_d2i(X509_EXTENSION *ext) +{ + const X509V3_EXT_METHOD *method; + const unsigned char *p; + + 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_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, errcode); + return 0; +} diff --git a/external/boringssl/crypto/x509v3/v3_ncons.c b/external/boringssl/crypto/x509v3/v3_ncons.c new file mode 100644 index 0000000000..368ad27268 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_ncons.c @@ -0,0 +1,482 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include + +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, 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, 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:"); + 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/external/boringssl/crypto/x509v3/v3_pci.c b/external/boringssl/crypto/x509v3/v3_pci.c new file mode 100644 index 0000000000..220f65e116 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pci.c @@ -0,0 +1,317 @@ +/* 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 +#include + +#include +#include +#include +#include +#include + +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, + X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if (!(*language = OBJ_txt2obj(val->value, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "pathlen") == 0) { + if (*pathlen) { + OPENSSL_PUT_ERROR(X509V3, + X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if (!X509V3_get_value_int(val, pathlen)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "policy") == 0) { + unsigned char *tmp_data = NULL; + long val_len; + if (!*policy) { + *policy = ASN1_OCTET_STRING_new(); + if (!*policy) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + return 0; + } + free_policy = 1; + } + if (strncmp(val->value, "hex:", 4) == 0) { + unsigned char *tmp_data2 = + string_to_hex(val->value + 4, &val_len); + + if (!tmp_data2) { + OPENSSL_PUT_ERROR(X509V3, 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, 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, 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, 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, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG); + X509V3_conf_err(val); + goto err; + } + if (!tmp_data) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + } + return 1; + err: + if (free_policy) { + ASN1_OCTET_STRING_free(*policy); + *policy = NULL; + } + return 0; +} + +static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *value) +{ + PROXY_CERT_INFO_EXTENSION *pci = NULL; + STACK_OF(CONF_VALUE) *vals; + ASN1_OBJECT *language = NULL; + ASN1_INTEGER *pathlen = NULL; + ASN1_OCTET_STRING *policy = NULL; + 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, 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, 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, + 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, + X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY); + goto err; + } + + pci = PROXY_CERT_INFO_EXTENSION_new(); + if (!pci) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + + pci->proxyPolicy->policyLanguage = language; + language = NULL; + pci->proxyPolicy->policy = policy; + policy = NULL; + pci->pcPathLengthConstraint = pathlen; + pathlen = NULL; + goto end; + err: + 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/external/boringssl/crypto/x509v3/v3_pcia.c b/external/boringssl/crypto/x509v3/v3_pcia.c new file mode 100644 index 0000000000..3f285f30f5 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pcia.c @@ -0,0 +1,57 @@ +/* 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 +#include +#include + + +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/external/boringssl/crypto/x509v3/v3_pcons.c b/external/boringssl/crypto/x509v3/v3_pcons.c new file mode 100644 index 0000000000..1a4631432d --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pcons.c @@ -0,0 +1,139 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD + *method, void *bcons, STACK_OF(CONF_VALUE) + *extlist); +static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_policy_constraints = { + 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, 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, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION); + goto err; + } + + return pcons; + err: + POLICY_CONSTRAINTS_free(pcons); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_pku.c b/external/boringssl/crypto/x509v3/v3_pku.c new file mode 100644 index 0000000000..e4868b47d1 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pku.c @@ -0,0 +1,110 @@ +/* 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 + +#include +#include +#include +#include +#include + +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/external/boringssl/crypto/x509v3/v3_pmaps.c b/external/boringssl/crypto/x509v3/v3_pmaps.c new file mode 100644 index 0000000000..caacdb2738 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pmaps.c @@ -0,0 +1,154 @@ +/* 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 + +#include +#include +#include +#include +#include + +static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD + *method, void *pmps, STACK_OF(CONF_VALUE) + *extlist); + +const X509V3_EXT_METHOD v3_policy_mappings = { + 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, 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, 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, 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, ERR_R_MALLOC_FAILURE); + return NULL; + } + pmap->issuerDomainPolicy = obj1; + pmap->subjectDomainPolicy = obj2; + sk_POLICY_MAPPING_push(pmaps, pmap); + } + return pmaps; +} diff --git a/external/boringssl/crypto/x509v3/v3_prn.c b/external/boringssl/crypto/x509v3/v3_prn.c new file mode 100644 index 0000000000..2f5efcff07 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_prn.c @@ -0,0 +1,229 @@ +/* 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 + +#include +#include +#include +#include + +/* 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, "\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", indent, ""); + else + BIO_printf(out, "%*s", indent, ""); + return 1; + + case X509V3_EXT_PARSE_UNKNOWN: + 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/external/boringssl/crypto/x509v3/v3_purp.c b/external/boringssl/crypto/x509v3/v3_purp.c new file mode 100644 index 0000000000..f9324d4e08 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_purp.c @@ -0,0 +1,874 @@ +/* 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) +#define ku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) +#define xku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) +#define ns_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) + +static 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)) { + x509v3_cache_extensions(x); + } + 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, 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, 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(X509V3, 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, ERR_R_MALLOC_FAILURE); + xptable_free(ptmp); + return 0; + } + if (!sk_X509_PURPOSE_push(xptable, ptmp)) { + OPENSSL_PUT_ERROR(X509V3, 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)); +} + +/* + * g_x509_cache_extensions_lock is used to protect against concurrent calls + * to |x509v3_cache_extensions|. Ideally this would be done with a + * |CRYPTO_once_t| in the |X509| structure, but |CRYPTO_once_t| isn't public. + * Note: it's not entirely clear whether this lock is needed. Not all paths to + * this function took a lock in OpenSSL. + */ +static struct CRYPTO_STATIC_MUTEX g_x509_cache_extensions_lock = + CRYPTO_STATIC_MUTEX_INIT; + +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; + + CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock); + + if (x->ex_flags & EXFLAG_SET) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock); + 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 && + !ku_reject(x, KU_KEY_CERT_SIGN)) + 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; + + CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock); +} + +/* + * CA checks common to all purposes return codes: 0 not a CA 1 is a CA 2 + * basicConstraints absent so "maybe" a CA 3 basicConstraints absent but self + * signed V1. 4 basicConstraints absent but keyUsage present and keyCertSign + * asserted. + */ + +static int check_ca(const X509 *x) +{ + /* keyUsage if present should allow cert signing */ + if (ku_reject(x, KU_KEY_CERT_SIGN)) + return 0; + if (x->ex_flags & EXFLAG_BCONS) { + if (x->ex_flags & EXFLAG_CA) + return 1; + /* If basicConstraints says not a CA then say so */ + else + return 0; + } else { + /* we support V1 roots for... uh, I don't really know why. */ + if ((x->ex_flags & V1_ROOT) == V1_ROOT) + return 3; + /* + * If key usage present it must have certSign so tolerate it + */ + else if (x->ex_flags & EXFLAG_KUSAGE) + return 4; + /* Older certificates could have Netscape-specific CA types */ + else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA) + return 5; + /* can this still be regarded a CA certificate? I doubt it */ + return 0; + } +} + +int X509_check_ca(X509 *x) +{ + if (!(x->ex_flags & EXFLAG_SET)) { + x509v3_cache_extensions(x); + } + + return check_ca(x); +} + +/* Check SSL CA: common checks for SSL client and server */ +static int check_ssl_ca(const X509 *x) +{ + int ca_ret; + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA) + return ca_ret; + else + return 0; +} + +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (xku_reject(x, XKU_SSL_CLIENT)) + return 0; + if (ca) + return check_ssl_ca(x); + /* We need to do digital signatures or key agreement */ + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) + return 0; + /* nsCertType if present should allow SSL client use */ + if (ns_reject(x, NS_SSL_CLIENT)) + return 0; + return 1; +} + +/* + * Key usage needed for TLS/SSL server: digital signature, encipherment or + * key agreement. The ssl code can check this more thoroughly for individual + * key types. + */ +#define KU_TLS \ + KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT + +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC)) + return 0; + if (ca) + return check_ssl_ca(x); + + if (ns_reject(x, NS_SSL_SERVER)) + return 0; + if (ku_reject(x, KU_TLS)) + return 0; + + return 1; + +} + +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = check_purpose_ssl_server(xp, x, ca); + if (!ret || ca) + return ret; + /* We need to encipher or Netscape complains */ + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +/* common S/MIME checks */ +static int purpose_smime(const X509 *x, int ca) +{ + if (xku_reject(x, XKU_SMIME)) + return 0; + if (ca) { + int ca_ret; + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) + return ca_ret; + else + return 0; + } + if (x->ex_flags & EXFLAG_NSCERT) { + if (x->ex_nscert & NS_SMIME) + return 1; + /* Workaround for some buggy certificates */ + if (x->ex_nscert & NS_SSL_CLIENT) + return 2; + return 0; + } + return 1; +} + +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) + return 0; + return ret; +} + +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (ca) { + int ca_ret; + if ((ca_ret = check_ca(x)) != 2) + return ca_ret; + else + return 0; + } + if (ku_reject(x, KU_CRL_SIGN)) + return 0; + return 1; +} + +/* + * OCSP helper: this is *not* a full OCSP check. It just checks that each CA + * is valid. Additional checks must be made on the chain. + */ + +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + /* + * Must be a valid CA. Should we really support the "I don't know" value + * (2)? + */ + if (ca) + return check_ca(x); + /* leaf certificate is checked in OCSP_verify() */ + return 1; +} + +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int i_ext; + + /* If ca is true we must return if this is a valid CA certificate. */ + if (ca) + return check_ca(x); + + /* + * Check the optional key usage field: + * if Key Usage is present, it must be one of digitalSignature + * and/or nonRepudiation (other values are not consistent and shall + * be rejected). + */ + if ((x->ex_flags & EXFLAG_KUSAGE) + && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || + !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) + return 0; + + /* Only time stamp key usage is permitted and it's required. */ + if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) + return 0; + + /* Extended Key Usage MUST be critical */ + i_ext = X509_get_ext_by_NID((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/external/boringssl/crypto/x509v3/v3_skey.c b/external/boringssl/crypto/x509v3/v3_skey.c new file mode 100644 index 0000000000..65f8287c1c --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_skey.c @@ -0,0 +1,152 @@ +/* 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 +#include + +#include +#include +#include +#include + +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, 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, 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, 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, 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, ERR_R_MALLOC_FAILURE); + goto err; + } + + return oct; + + err: + M_ASN1_OCTET_STRING_free(oct); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_sxnet.c b/external/boringssl/crypto/x509v3/v3_sxnet.c new file mode 100644 index 0000000000..51c5a676f0 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_sxnet.c @@ -0,0 +1,274 @@ +/* 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +/* 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, 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, 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, X509V3_R_INVALID_NULL_ARGUMENT); + return 0; + } + if (userlen == -1) + userlen = strlen(user); + if (userlen > 64) { + OPENSSL_PUT_ERROR(X509V3, 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, 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, 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, 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, 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/external/boringssl/crypto/x509v3/v3_utl.c b/external/boringssl/crypto/x509v3/v3_utl.c new file mode 100644 index 0000000000..a238a20ec8 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_utl.c @@ -0,0 +1,1327 @@ +/* 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../conf/internal.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_new())) + 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, 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, 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, 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, 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, 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, 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_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); + if (linebuf == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + state = HDR_NAME; + ntmp = NULL; + /* Go through all characters */ + for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); + p++) { + + switch (state) { + case HDR_NAME: + if (c == ':') { + state = HDR_VALUE; + *p = 0; + ntmp = strip_spaces(q); + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, 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_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_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_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_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, 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, 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, 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, ERR_R_MALLOC_FAILURE); + return NULL; + + badhex: + OPENSSL_free(hexbuf); + OPENSSL_PUT_ERROR(X509V3, 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 + 1] == '.'); + /* + * At most one wildcard per pattern. + * No wildcards in IDNA labels. + * No wildcards after the first label. + */ + if (star != NULL || (state & LABEL_IDNA) != 0 || dots) + return NULL; + /* Only full-label '*.example.com' wildcards? */ + if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) + && (!atstart || !atend)) + return NULL; + /* No 'foo*bar' wildcards */ + if (!atstart && !atend) + return NULL; + star = &p[i]; + state &= ~LABEL_START; + } else if ((state & LABEL_START) != 0) { + /* + * At the start of a label, skip any "xn--" and + * remain in the LABEL_START state, but set the + * IDNA label state + */ + if ((state & LABEL_IDNA) == 0 && len - i >= 4 + && 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] == '-') { + /* no domain/subdomain starts with '-' */ + if ((state & LABEL_START) != 0) + return NULL; + state |= LABEL_HYPHEN; + } else + return NULL; + } + + /* + * The final label must not end in a hyphen or ".", and + * there must be at least two dots after the star. + */ + if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) + return NULL; + return star; +} + +/* Compare using wildcards. */ +static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + const unsigned char *star = NULL; + + /* + * Subject names starting with '.' can only match a wildcard pattern + * via a subject sub-domain pattern suffix match. + */ + if (!(subject_len > 1 && subject[0] == '.')) + star = valid_star(pattern, pattern_len, flags); + if (star == NULL) + return equal_nocase(pattern, pattern_len, + subject, subject_len, flags); + return wildcard_match(pattern, star - pattern, + star + 1, (pattern + pattern_len) - star - 1, + subject, subject_len, flags); +} + +/* + * Compare an ASN1_STRING to a supplied string. If they match return 1. If + * cmp_type > 0 only compare if string matches the type, otherwise convert it + * to UTF8. + */ + +static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, + unsigned int flags, const char *b, size_t blen, + char **peername) +{ + int rv = 0; + + if (!a->data || !a->length) + return 0; + if (cmp_type > 0) { + if (cmp_type != a->type) + return 0; + if (cmp_type == V_ASN1_IA5STRING) + rv = equal(a->data, a->length, (unsigned char *)b, blen, flags); + else if (a->length == (int)blen && !memcmp(a->data, b, blen)) + rv = 1; + if (rv > 0 && peername) + *peername = BUF_strndup((char *)a->data, a->length); + } else { + int astrlen; + unsigned char *astr; + astrlen = ASN1_STRING_to_UTF8(&astr, a); + if (astrlen < 0) + return -1; + rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); + if (rv > 0 && peername) + *peername = BUF_strndup((char *)astr, astrlen); + OPENSSL_free(astr); + } + return rv; +} + +static int do_x509_check(X509 *x, const char *chk, size_t chklen, + unsigned int flags, int check_type, char **peername) +{ + GENERAL_NAMES *gens = NULL; + X509_NAME *name = NULL; + size_t i; + int j; + int cnid = NID_undef; + int alt_type; + int san_present = 0; + int rv = 0; + equal_fn equal; + + /* See below, this flag is internal-only */ + flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS; + if (check_type == GEN_EMAIL) { + cnid = NID_pkcs9_emailAddress; + alt_type = V_ASN1_IA5STRING; + equal = equal_email; + } else if (check_type == GEN_DNS) { + cnid = NID_commonName; + /* Implicit client-side DNS sub-domain pattern */ + if (chklen > 1 && chk[0] == '.') + flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS; + alt_type = V_ASN1_IA5STRING; + if (flags & X509_CHECK_FLAG_NO_WILDCARDS) + equal = equal_nocase; + else + equal = equal_wildcard; + } else { + alt_type = V_ASN1_OCTET_STRING; + equal = equal_case; + } + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + if (gens) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + GENERAL_NAME *gen; + ASN1_STRING *cstr; + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type != check_type) + continue; + san_present = 1; + if (check_type == GEN_EMAIL) + cstr = gen->d.rfc822Name; + else if (check_type == GEN_DNS) + cstr = gen->d.dNSName; + else + cstr = gen->d.iPAddress; + /* Positive on success, negative on error! */ + if ((rv = do_check_string(cstr, alt_type, equal, flags, + chk, chklen, peername)) != 0) + break; + } + GENERAL_NAMES_free(gens); + if (rv != 0) + return rv; + if (cnid == NID_undef + || (san_present + && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))) + return 0; + } + + /* We're done if CN-ID is not pertinent */ + if (cnid == NID_undef) + return 0; + + j = -1; + name = X509_get_subject_name(x); + while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { + X509_NAME_ENTRY *ne; + ASN1_STRING *str; + ne = X509_NAME_get_entry(name, j); + str = X509_NAME_ENTRY_get_data(ne); + /* Positive on success, negative on error! */ + if ((rv = do_check_string(str, -1, equal, flags, + chk, chklen, peername)) != 0) + return rv; + } + return 0; +} + +int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) +{ + if (chk == NULL) + return -2; + if (memchr(chk, '\0', chklen)) + return -2; + return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); +} + +int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags) +{ + if (chk == NULL) + return -2; + if (memchr(chk, '\0', chklen)) + return -2; + return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); +} + +int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags) +{ + if (chk == NULL) + return -2; + return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); +} + +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) +{ + unsigned char ipout[16]; + size_t iplen; + + if (ipasc == NULL) + return -2; + iplen = (size_t)a2i_ipadd(ipout, ipasc); + if (iplen == 0) + return -2; + return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); +} + +/* + * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible + * with RFC3280. + */ + +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) +{ + unsigned char ipout[16]; + ASN1_OCTET_STRING *ret; + int iplen; + + /* If string contains a ':' assume IPv6 */ + + iplen = a2i_ipadd(ipout, ipasc); + + if (!iplen) + return NULL; + + ret = ASN1_OCTET_STRING_new(); + if (!ret) + 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/external/boringssl/crypto/x509v3/v3name_test.c b/external/boringssl/crypto/x509v3/v3name_test.c new file mode 100644 index 0000000000..dadf488f53 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3name_test.c @@ -0,0 +1,410 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include + +static const char *const names[] = { + "a", "b", ".", "*", "@", + ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..", + "-example.com", "example-.com", + "@@", "**", "*.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", + "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com", + "*.good--example.com", "www.good--example.com", + "*.xn--bar.com", "xn--foo.xn--bar.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: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]", + "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]", + "set CN: host: [*.good--example.com] matches [www.good--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 dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]", + "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]", + "set dnsName: host: [*.good--example.com] matches [www.good--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, 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, name, namelen, 0, NULL); + 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, name, namelen, + X509_CHECK_FLAG_NO_WILDCARDS, NULL); + 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, 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/external/boringssl/decrepit/CMakeLists.txt b/external/boringssl/decrepit/CMakeLists.txt new file mode 100644 index 0000000000..6a5462c2b6 --- /dev/null +++ b/external/boringssl/decrepit/CMakeLists.txt @@ -0,0 +1,35 @@ +add_subdirectory(bio) +add_subdirectory(blowfish) +add_subdirectory(cast) +add_subdirectory(des) +add_subdirectory(dh) +add_subdirectory(dsa) +add_subdirectory(evp) +add_subdirectory(obj) +add_subdirectory(rc4) +add_subdirectory(ripemd) +add_subdirectory(rsa) +add_subdirectory(ssl) +add_subdirectory(x509) +add_subdirectory(xts) + +add_library( + decrepit + + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ +) + +target_link_libraries(decrepit crypto ssl) diff --git a/external/boringssl/decrepit/bio/CMakeLists.txt b/external/boringssl/decrepit/bio/CMakeLists.txt new file mode 100644 index 0000000000..95d9231157 --- /dev/null +++ b/external/boringssl/decrepit/bio/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + bio_decrepit + + OBJECT + + base64_bio.c +) diff --git a/external/boringssl/decrepit/bio/base64_bio.c b/external/boringssl/decrepit/bio/base64_bio.c new file mode 100644 index 0000000000..8415bfedb4 --- /dev/null +++ b/external/boringssl/decrepit/bio/base64_bio.c @@ -0,0 +1,536 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define B64_BLOCK_SIZE 1024 +#define B64_BLOCK_SIZE2 768 +#define B64_NONE 0 +#define B64_ENCODE 1 +#define B64_DECODE 2 +#define EVP_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80) + +typedef struct b64_struct { + int buf_len; + int buf_off; + int tmp_len; /* used to find the start when decoding */ + int tmp_nl; /* If true, scan until '\n' */ + int encode; + int start; /* have we started decoding yet? */ + int cont; /* <= 0 when finished */ + EVP_ENCODE_CTX base64; + char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; + char tmp[B64_BLOCK_SIZE]; +} BIO_B64_CTX; + +static int b64_new(BIO *bio) { + BIO_B64_CTX *ctx; + + ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx == NULL) { + return 0; + } + + memset(ctx, 0, sizeof(*ctx)); + + ctx->cont = 1; + ctx->start = 1; + + bio->init = 1; + bio->ptr = (char *)ctx; + return 1; +} + +static int b64_free(BIO *bio) { + if (bio == NULL) { + return 0; + } + OPENSSL_free(bio->ptr); + bio->ptr = NULL; + bio->init = 0; + bio->flags = 0; + return 1; +} + +static int b64_read(BIO *b, char *out, int outl) { + int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; + BIO_B64_CTX *ctx; + uint8_t *p, *q; + + if (out == NULL) { + return 0; + } + ctx = (BIO_B64_CTX *) b->ptr; + + if (ctx == NULL || b->next_bio == NULL) { + return 0; + } + + BIO_clear_retry_flags(b); + + if (ctx->encode != B64_DECODE) { + ctx->encode = B64_DECODE; + ctx->buf_len = 0; + ctx->buf_off = 0; + ctx->tmp_len = 0; + EVP_DecodeInit(&ctx->base64); + } + + /* First check if there are bytes decoded/encoded */ + if (ctx->buf_len > 0) { + assert(ctx->buf_len >= ctx->buf_off); + i = ctx->buf_len - ctx->buf_off; + if (i > outl) { + i = outl; + } + assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); + memcpy(out, &ctx->buf[ctx->buf_off], i); + ret = i; + out += i; + outl -= i; + ctx->buf_off += i; + if (ctx->buf_len == ctx->buf_off) { + ctx->buf_len = 0; + ctx->buf_off = 0; + } + } + + /* At this point, we have room of outl bytes and an empty buffer, so we + * should read in some more. */ + + ret_code = 0; + while (outl > 0) { + if (ctx->cont <= 0) { + break; + } + + i = BIO_read(b->next_bio, &(ctx->tmp[ctx->tmp_len]), + B64_BLOCK_SIZE - ctx->tmp_len); + + if (i <= 0) { + ret_code = i; + + /* Should we continue next time we are called? */ + if (!BIO_should_retry(b->next_bio)) { + ctx->cont = i; + /* If buffer empty break */ + if (ctx->tmp_len == 0) { + break; + } else { + /* Fall through and process what we have */ + i = 0; + } + } else { + /* else we retry and add more data to buffer */ + break; + } + } + i += ctx->tmp_len; + ctx->tmp_len = i; + + /* We need to scan, a line at a time until we have a valid line if we are + * starting. */ + if (ctx->start && (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL))) { + /* ctx->start = 1; */ + ctx->tmp_len = 0; + } else if (ctx->start) { + q = p = (uint8_t *)ctx->tmp; + num = 0; + for (j = 0; j < i; j++) { + if (*(q++) != '\n') { + continue; + } + + /* due to a previous very long line, we need to keep on scanning for a + * '\n' before we even start looking for base64 encoded stuff. */ + if (ctx->tmp_nl) { + p = q; + ctx->tmp_nl = 0; + continue; + } + + k = EVP_DecodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, &num, p, + q - p); + + if (k <= 0 && num == 0 && ctx->start) { + EVP_DecodeInit(&ctx->base64); + } else { + if (p != (uint8_t *)&(ctx->tmp[0])) { + i -= (p - (uint8_t *)&(ctx->tmp[0])); + for (x = 0; x < i; x++) { + ctx->tmp[x] = p[x]; + } + } + EVP_DecodeInit(&ctx->base64); + ctx->start = 0; + break; + } + p = q; + } + + /* we fell off the end without starting */ + if (j == i && num == 0) { + /* Is this is one long chunk?, if so, keep on reading until a new + * line. */ + if (p == (uint8_t *)&(ctx->tmp[0])) { + /* Check buffer full */ + if (i == B64_BLOCK_SIZE) { + ctx->tmp_nl = 1; + ctx->tmp_len = 0; + } + } else if (p != q) { /* finished on a '\n' */ + n = q - p; + for (ii = 0; ii < n; ii++) { + ctx->tmp[ii] = p[ii]; + } + ctx->tmp_len = n; + } + /* else finished on a '\n' */ + continue; + } else { + ctx->tmp_len = 0; + } + } else if (i < B64_BLOCK_SIZE && ctx->cont > 0) { + /* If buffer isn't full and we can retry then restart to read in more + * data. */ + continue; + } + + if (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL)) { + int z, jj; + + jj = i & ~3; /* process per 4 */ + z = EVP_DecodeBlock((uint8_t *)ctx->buf, (uint8_t *)ctx->tmp, jj); + if (jj > 2) { + if (ctx->tmp[jj - 1] == '=') { + z--; + if (ctx->tmp[jj - 2] == '=') { + z--; + } + } + } + /* z is now number of output bytes and jj is the number consumed. */ + if (jj != i) { + memmove(ctx->tmp, &ctx->tmp[jj], i - jj); + ctx->tmp_len = i - jj; + } + ctx->buf_len = 0; + if (z > 0) { + ctx->buf_len = z; + } + i = z; + } else { + i = EVP_DecodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, + &ctx->buf_len, (uint8_t *)ctx->tmp, i); + ctx->tmp_len = 0; + } + ctx->buf_off = 0; + if (i < 0) { + ret_code = 0; + ctx->buf_len = 0; + break; + } + + if (ctx->buf_len <= outl) { + i = ctx->buf_len; + } else { + i = outl; + } + + memcpy(out, ctx->buf, i); + ret += i; + ctx->buf_off = i; + if (ctx->buf_off == ctx->buf_len) { + ctx->buf_len = 0; + ctx->buf_off = 0; + } + outl -= i; + out += i; + } + + BIO_copy_next_retry(b); + return ret == 0 ? ret_code : ret; +} + +static int b64_write(BIO *b, const char *in, int inl) { + int ret = 0, n, i; + BIO_B64_CTX *ctx; + + ctx = (BIO_B64_CTX *)b->ptr; + BIO_clear_retry_flags(b); + + if (ctx->encode != B64_ENCODE) { + ctx->encode = B64_ENCODE; + ctx->buf_len = 0; + ctx->buf_off = 0; + ctx->tmp_len = 0; + EVP_EncodeInit(&(ctx->base64)); + } + + assert(ctx->buf_off < (int)sizeof(ctx->buf)); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + + n = ctx->buf_len - ctx->buf_off; + while (n > 0) { + i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return i; + } + assert(i <= n); + ctx->buf_off += i; + assert(ctx->buf_off <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + n -= i; + } + + /* at this point all pending data has been written. */ + ctx->buf_off = 0; + ctx->buf_len = 0; + + if (in == NULL || inl <= 0) { + return 0; + } + + while (inl > 0) { + n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; + + if (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL)) { + if (ctx->tmp_len > 0) { + assert(ctx->tmp_len <= 3); + n = 3 - ctx->tmp_len; + /* There's a theoretical possibility of this. */ + if (n > inl) { + n = inl; + } + memcpy(&(ctx->tmp[ctx->tmp_len]), in, n); + ctx->tmp_len += n; + ret += n; + if (ctx->tmp_len < 3) { + break; + } + ctx->buf_len = EVP_EncodeBlock((uint8_t *)ctx->buf, (uint8_t *)ctx->tmp, + ctx->tmp_len); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + + /* Since we're now done using the temporary buffer, the length should + * be zeroed. */ + ctx->tmp_len = 0; + } else { + if (n < 3) { + memcpy(ctx->tmp, in, n); + ctx->tmp_len = n; + ret += n; + break; + } + n -= n % 3; + ctx->buf_len = + EVP_EncodeBlock((uint8_t *)ctx->buf, (const uint8_t *)in, n); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + ret += n; + } + } else { + EVP_EncodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, &ctx->buf_len, + (uint8_t *)in, n); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + ret += n; + } + inl -= n; + in += n; + + ctx->buf_off = 0; + n = ctx->buf_len; + + while (n > 0) { + i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return ret == 0 ? i : ret; + } + assert(i <= n); + n -= i; + ctx->buf_off += i; + assert(ctx->buf_off <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + } + ctx->buf_len = 0; + ctx->buf_off = 0; + } + return ret; +} + +static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) { + BIO_B64_CTX *ctx; + long ret = 1; + int i; + + ctx = (BIO_B64_CTX *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->cont = 1; + ctx->start = 1; + ctx->encode = B64_NONE; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + case BIO_CTRL_EOF: /* More to read */ + if (ctx->cont <= 0) { + ret = 1; + } else { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_CTRL_WPENDING: /* More to write in buffer */ + assert(ctx->buf_len >= ctx->buf_off); + ret = ctx->buf_len - ctx->buf_off; + if ((ret == 0) && (ctx->encode != B64_NONE) && (ctx->base64.data_used != 0)) { + ret = 1; + } else if (ret <= 0) { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_CTRL_PENDING: /* More to read in buffer */ + assert(ctx->buf_len >= ctx->buf_off); + ret = ctx->buf_len - ctx->buf_off; + if (ret <= 0) { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_CTRL_FLUSH: + /* do a final write */ + again: + while (ctx->buf_len != ctx->buf_off) { + i = b64_write(b, NULL, 0); + if (i < 0) { + return i; + } + } + if (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL)) { + if (ctx->tmp_len != 0) { + ctx->buf_len = EVP_EncodeBlock((uint8_t *)ctx->buf, + (uint8_t *)ctx->tmp, ctx->tmp_len); + ctx->buf_off = 0; + ctx->tmp_len = 0; + goto again; + } + } else if (ctx->encode != B64_NONE && ctx->base64.data_used != 0) { + ctx->buf_off = 0; + EVP_EncodeFinal(&(ctx->base64), (uint8_t *)ctx->buf, &(ctx->buf_len)); + /* push out the bytes */ + goto again; + } + /* Finally flush the underlying BIO */ + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + case BIO_CTRL_INFO: + case BIO_CTRL_GET: + case BIO_CTRL_SET: + default: + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + } + return ret; +} + +static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) { + long ret = 1; + + if (b->next_bio == NULL) { + return 0; + } + switch (cmd) { + default: + ret = BIO_callback_ctrl(b->next_bio, cmd, fp); + break; + } + return ret; +} + +static int b64_puts(BIO *b, const char *str) { + return b64_write(b, str, strlen(str)); +} + +static const BIO_METHOD b64_method = { + BIO_TYPE_BASE64, "base64 encoding", b64_write, b64_read, b64_puts, + NULL /* gets */, b64_ctrl, b64_new, b64_free, b64_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_base64(void) { return &b64_method; } diff --git a/external/boringssl/decrepit/blowfish/CMakeLists.txt b/external/boringssl/decrepit/blowfish/CMakeLists.txt new file mode 100644 index 0000000000..29729c4982 --- /dev/null +++ b/external/boringssl/decrepit/blowfish/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + blowfish + + OBJECT + + blowfish.c +) diff --git a/external/boringssl/decrepit/blowfish/blowfish.c b/external/boringssl/decrepit/blowfish/blowfish.c new file mode 100644 index 0000000000..e277f3446b --- /dev/null +++ b/external/boringssl/decrepit/blowfish/blowfish.c @@ -0,0 +1,493 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "../macros.h" + + +#define BF_ENC(LL, R, S, P) \ + (LL ^= P, \ + LL ^= \ + (((S[((int)(R >> 24) & 0xff)] + S[0x0100 + ((int)(R >> 16) & 0xff)]) ^ \ + S[0x0200 + ((int)(R >> 8) & 0xff)]) + \ + S[0x0300 + ((int)(R)&0xff)]) & \ + 0xffffffffL) + +void BF_encrypt(uint32_t *data, const BF_KEY *key) { + uint32_t l, r; + const uint32_t *p, *s; + + p = key->P; + s = &(key->S[0]); + l = data[0]; + r = data[1]; + + l ^= p[0]; + BF_ENC(r, l, s, p[1]); + BF_ENC(l, r, s, p[2]); + BF_ENC(r, l, s, p[3]); + BF_ENC(l, r, s, p[4]); + BF_ENC(r, l, s, p[5]); + BF_ENC(l, r, s, p[6]); + BF_ENC(r, l, s, p[7]); + BF_ENC(l, r, s, p[8]); + BF_ENC(r, l, s, p[9]); + BF_ENC(l, r, s, p[10]); + BF_ENC(r, l, s, p[11]); + BF_ENC(l, r, s, p[12]); + BF_ENC(r, l, s, p[13]); + BF_ENC(l, r, s, p[14]); + BF_ENC(r, l, s, p[15]); + BF_ENC(l, r, s, p[16]); + r ^= p[BF_ROUNDS + 1]; + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void BF_decrypt(uint32_t *data, const BF_KEY *key) { + uint32_t l, r; + const uint32_t *p, *s; + + p = key->P; + s = &(key->S[0]); + l = data[0]; + r = data[1]; + + l ^= p[BF_ROUNDS + 1]; + BF_ENC(r, l, s, p[16]); + BF_ENC(l, r, s, p[15]); + BF_ENC(r, l, s, p[14]); + BF_ENC(l, r, s, p[13]); + BF_ENC(r, l, s, p[12]); + BF_ENC(l, r, s, p[11]); + BF_ENC(r, l, s, p[10]); + BF_ENC(l, r, s, p[9]); + BF_ENC(r, l, s, p[8]); + BF_ENC(l, r, s, p[7]); + BF_ENC(r, l, s, p[6]); + BF_ENC(l, r, s, p[5]); + BF_ENC(r, l, s, p[4]); + BF_ENC(l, r, s, p[3]); + BF_ENC(r, l, s, p[2]); + BF_ENC(l, r, s, p[1]); + r ^= p[0]; + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void BF_ecb_encrypt(const uint8_t *in, uint8_t *out, + const BF_KEY *key, int encrypt) { + uint32_t d[2]; + + n2l(in, d[0]); + n2l(in, d[1]); + if (encrypt) { + BF_encrypt(d, key); + } else { + BF_decrypt(d, key); + } + l2n(d[0], out); + l2n(d[1], out); +} + +void BF_cbc_encrypt(const uint8_t *in, uint8_t *out, long length, + const BF_KEY *schedule, uint8_t *ivec, int encrypt) { + uint32_t tin0, tin1; + uint32_t tout0, tout1, xor0, xor1; + long l = length; + uint32_t tin[2]; + + if (encrypt) { + n2l(ivec, tout0); + n2l(ivec, tout1); + ivec -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + BF_encrypt(tin, schedule); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + if (l != -8) { + n2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + BF_encrypt(tin, schedule); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + l2n(tout0, ivec); + l2n(tout1, ivec); + } else { + n2l(ivec, xor0); + n2l(ivec, xor1); + ivec -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + BF_decrypt(tin, schedule); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2n(tout0, out); + l2n(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + BF_decrypt(tin, schedule); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2nn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2n(xor0, ivec); + l2n(xor1, ivec); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +static const BF_KEY bf_init = { + {0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L, 0xa4093822L, + 0x299f31d0L, 0x082efa98L, 0xec4e6c89L, 0x452821e6L, 0x38d01377L, + 0xbe5466cfL, 0x34e90c6cL, 0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, + 0xb5470917L, 0x9216d5d9L, 0x8979fb1b}, + { + 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L, 0xb8e1afedL, + 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L, 0x24a19947L, 0xb3916cf7L, + 0x0801f2e2L, 0x858efc16L, 0x636920d8L, 0x71574e69L, 0xa458fea3L, + 0xf4933d7eL, 0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL, + 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L, 0xc5d1b023L, + 0x286085f0L, 0xca417918L, 0xb8db38efL, 0x8e79dcb0L, 0x603a180eL, + 0x6c9e0e8bL, 0xb01e8a3eL, 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, + 0x55605c60L, 0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L, + 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL, 0xa15486afL, + 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL, 0x2ba9c55dL, 0x741831f6L, + 0xce5c3e16L, 0x9b87931eL, 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, + 0x28958677L, 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L, + 0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L, 0xef845d5dL, + 0xe98575b1L, 0xdc262302L, 0xeb651b88L, 0x23893e81L, 0xd396acc5L, + 0x0f6d6ff3L, 0x83f44239L, 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, + 0x9e1f9b5eL, 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L, + 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L, 0x6eef0b6cL, + 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L, 0xa1f1651dL, 0x39af0176L, + 0x66ca593eL, 0x82430e88L, 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, + 0x3b8b5ebeL, 0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L, + 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL, 0x37d0d724L, + 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL, 0x075372c9L, 0x80991b7bL, + 0x25d479d8L, 0xf6e8def7L, 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, + 0x04c006baL, 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L, + 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL, 0x6dfc511fL, + 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L, 0xbee3d004L, 0xde334afdL, + 0x660f2807L, 0x192e4bb3L, 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, + 0xb9d3fbdbL, 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L, + 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L, 0x3c7516dfL, + 0xfd616b15L, 0x2f501ec8L, 0xad0552abL, 0x323db5faL, 0xfd238760L, + 0x53317b48L, 0x3e00df82L, 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, + 0xdf1769dbL, 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L, + 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L, 0x10fa3d98L, + 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL, 0x9a53e479L, 0xb6f84565L, + 0xd28e49bcL, 0x4bfb9790L, 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, + 0xcee4c6e8L, 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L, + 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L, 0xd08ed1d0L, + 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L, 0x8ff6e2fbL, 0xf2122b64L, + 0x8888b812L, 0x900df01cL, 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, + 0xb3a8c1adL, 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L, + 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L, 0xb4a84fe0L, + 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L, 0x165fa266L, 0x80957705L, + 0x93cc7314L, 0x211a1477L, 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, + 0xfb9d35cfL, 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L, + 0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL, 0x2464369bL, + 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL, 0x78c14389L, 0xd95a537fL, + 0x207d5ba2L, 0x02e5b9c5L, 0x83260376L, 0x6295cfa9L, 0x11c81968L, + 0x4e734a41L, 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L, + 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L, 0x08ba6fb5L, + 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L, 0xb6636521L, 0xe7b9f9b6L, + 0xff34052eL, 0xc5855664L, 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, + 0x6e85076aL, 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L, + 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L, 0xecaa8c71L, + 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L, 0x193602a5L, 0x75094c29L, + 0xa0591340L, 0xe4183a3eL, 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, + 0x99f73fd6L, 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L, + 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL, 0x09686b3fL, + 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L, 0x687f3584L, 0x52a0e286L, + 0xb79c5305L, 0xaa500737L, 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, + 0x5716f2b8L, 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL, + 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL, 0xd19113f9L, + 0x7ca92ff6L, 0x94324773L, 0x22f54701L, 0x3ae5e581L, 0x37c2dadcL, + 0xc8b57634L, 0x9af3dda7L, 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, + 0xa4751e41L, 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L, + 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL, 0x2cb81290L, + 0x24977c79L, 0x5679b072L, 0xbcaf89afL, 0xde9a771fL, 0xd9930810L, + 0xb38bae12L, 0xdccf3f2eL, 0x5512721fL, 0x2e6b7124L, 0x501adde6L, + 0x9f84cd87L, 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL, + 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L, 0xef1c1847L, + 0x3215d908L, 0xdd433b37L, 0x24c2ba16L, 0x12a14d43L, 0x2a65c451L, + 0x50940002L, 0x133ae4ddL, 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, + 0x5f11199bL, 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L, + 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL, 0x86e34570L, + 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L, 0x771fe71cL, 0x4e3d06faL, + 0x2965dcb9L, 0x99e71d0fL, 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, + 0x9c10b36aL, 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L, + 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L, 0x5223a708L, + 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L, 0xe3bc4595L, 0xa67bc883L, + 0xb17f37d1L, 0x018cff28L, 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, + 0x68ab9802L, 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L, + 0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L, 0x13cca830L, + 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL, 0xb5735c90L, 0x4c70a239L, + 0xd59e9e0bL, 0xcbaade14L, 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, + 0xb2f3846eL, 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L, + 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L, 0x9b540b19L, + 0x875fa099L, 0x95f7997eL, 0x623d7da8L, 0xf837889aL, 0x97e32d77L, + 0x11ed935fL, 0x16681281L, 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, + 0x7858ba99L, 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L, + 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L, 0x58ebf2efL, + 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L, 0x5d4a14d9L, 0xe864b7e3L, + 0x42105d14L, 0x203e13e0L, 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, + 0xfacb4fd0L, 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L, + 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L, 0xcf62a1f2L, + 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L, 0x7f1524c3L, 0x69cb7492L, + 0x47848a0bL, 0x5692b285L, 0x095bbf00L, 0xad19489dL, 0x1462b174L, + 0x23820e00L, 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L, + 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL, 0x7cde3759L, + 0xcbee7460L, 0x4085f2a7L, 0xce77326eL, 0xa6078084L, 0x19f8509eL, + 0xe8efd855L, 0x61d99735L, 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, + 0x800bcadcL, 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L, + 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L, 0xc5c43465L, + 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L, 0x153e21e7L, 0x8fb03d4aL, + 0xe6e39f2bL, 0xdb83adf7L, 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, + 0x94692934L, 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L, + 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL, 0x1e39f62eL, + 0x97244546L, 0x14214f74L, 0xbf8b8840L, 0x4d95fc1dL, 0x96b591afL, + 0x70f4ddd3L, 0x66a02f45L, 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, + 0x31cb8504L, 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL, + 0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL, 0x68dc1462L, + 0xd7486900L, 0x680ec0a4L, 0x27a18deeL, 0x4f3ffea2L, 0xe887ad8cL, + 0xb58ce006L, 0x7af4d6b6L, 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, + 0x406b2a42L, 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL, + 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L, 0x3a6efa74L, + 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL, 0xfb0af54eL, 0xd8feb397L, + 0x454056acL, 0xba489527L, 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, + 0xd096954bL, 0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L, + 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL, 0xfdf8e802L, + 0x04272f70L, 0x80bb155cL, 0x05282ce3L, 0x95c11548L, 0xe4c66d22L, + 0x48c1133fL, 0xc70f86dcL, 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, + 0x5d886e17L, 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L, + 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL, 0x0e12b4c2L, + 0x02e1329eL, 0xaf664fd1L, 0xcad18115L, 0x6b2395e0L, 0x333e92e1L, + 0x3b240b62L, 0xeebeb922L, 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, + 0x2da2f728L, 0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L, + 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL, 0x0a476341L, + 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L, 0xa812dc60L, 0xa1ebddf8L, + 0x991be14cL, 0xdb6e6b0dL, 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, + 0xdcd0e804L, 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL, + 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L, 0xbb132f88L, + 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL, 0x37392eb3L, 0xcc115979L, + 0x8026e297L, 0xf42e312dL, 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, + 0x782ef11cL, 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L, + 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L, 0x44421659L, + 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL, 0x64af674eL, 0xda86a85fL, + 0xbebfe988L, 0x64e4c3feL, 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, + 0x6003604dL, 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL, + 0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL, 0x77a057beL, + 0xbde8ae24L, 0x55464299L, 0xbf582e61L, 0x4e58f48fL, 0xf2ddfda2L, + 0xf474ef38L, 0x8789bdc2L, 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, + 0x46fcd9b9L, 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L, + 0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL, 0xb90bace1L, + 0xbb8205d0L, 0x11a86248L, 0x7574a99eL, 0xb77f19b6L, 0xe0a9dc09L, + 0x662d09a1L, 0xc4324633L, 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, + 0x1d6efe10L, 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L, + 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L, 0x50115e01L, + 0xa70683faL, 0xa002b5c4L, 0x0de6d027L, 0x9af88c27L, 0x773f8641L, + 0xc3604c06L, 0x61a806b5L, 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, + 0x30dc7d62L, 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L, + 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L, 0x6f05e409L, + 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L, 0x86e3725fL, 0x724d9db9L, + 0x1ac15bb4L, 0xd39eb8fcL, 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, + 0x4dad0fc4L, 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL, + 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L, 0xd79a3234L, + 0x92638212L, 0x670efa8eL, 0x406000e0L, 0x3a39ce37L, 0xd3faf5cfL, + 0xabc27737L, 0x5ac52d1bL, 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, + 0x99bc9bbeL, 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL, + 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L, 0x5748ab2fL, + 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L, 0x530ff8eeL, 0x468dde7dL, + 0xd5730a1dL, 0x4cd04dc6L, 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, + 0xbe5ee304L, 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L, + 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L, 0x83c061baL, + 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L, 0x2826a2f9L, 0xa73a3ae1L, + 0x4ba99586L, 0xef5562e9L, 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, + 0x77fa0a59L, 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L, + 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L, 0x96d5ac3aL, + 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L, 0x1f9f25cfL, 0xadf2b89bL, + 0x5ad6b472L, 0x5a88f54cL, 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, + 0xed93fa9bL, 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L, + 0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL, 0x15056dd4L, + 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL, 0xc3eb9e15L, 0x3c9057a2L, + 0x97271aecL, 0xa93a072aL, 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, + 0x26dcf319L, 0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL, + 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL, 0x4de81751L, + 0x3830dc8eL, 0x379d5862L, 0x9320f991L, 0xea7a90c2L, 0xfb3e7bceL, + 0x5121ce64L, 0x774fbe32L, 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, + 0x6413e680L, 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L, + 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL, 0x5bbef7ddL, + 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL, 0xdda26a7eL, 0x3a59ff45L, + 0x3e350a44L, 0xbcb4cdd5L, 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, + 0xbf3c6f47L, 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L, + 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL, 0x4040cb08L, + 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L, 0xe1b00428L, 0x95983a1dL, + 0x06b89fb4L, 0xce6ea048L, 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, + 0x277227f8L, 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL, + 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L, 0xe01cc87eL, + 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L, 0x1a908749L, 0xd44fbd9aL, + 0xd0dadecbL, 0xd50ada38L, 0x0339c32aL, 0xc6913667L, 0x8df9317cL, + 0xe0b12b4fL, 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL, + 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L, 0xfae59361L, + 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L, 0xb6c1075eL, 0xe3056a0cL, + 0x10d25065L, 0xcb03a442L, 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, + 0x3278e964L, 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL, + 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L, 0xdf359f8dL, + 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL, 0xe54cda54L, 0x1edad891L, + 0xce6279cfL, 0xcd3e7e6fL, 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, + 0xf6fb2299L, 0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L, + 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL, 0xde966292L, + 0x81b949d0L, 0x4c50901bL, 0x71c65614L, 0xe6c6c7bdL, 0x327a140aL, + 0x45e1d006L, 0xc3f27b9aL, 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, + 0x35bdd2f6L, 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL, + 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L, 0xba38209cL, + 0xf746ce76L, 0x77afa1c5L, 0x20756060L, 0x85cbfe4eL, 0x8ae88dd8L, + 0x7aaaf9b0L, 0x4cf9aa7eL, 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, + 0xd6ebe1f9L, 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL, + 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L, + }, +}; + +void BF_set_key(BF_KEY *key, size_t len, const uint8_t *data) { + int i; + uint32_t *p, ri, in[2]; + const uint8_t *d, *end; + + memcpy(key, &bf_init, sizeof(BF_KEY)); + p = key->P; + + if (len > ((BF_ROUNDS + 2) * 4)) + len = (BF_ROUNDS + 2) * 4; + + d = data; + end = &data[len]; + for (i = 0; i < BF_ROUNDS + 2; i++) { + ri = *(d++); + if (d >= end) { + d = data; + } + + ri <<= 8; + ri |= *(d++); + if (d >= end) { + d = data; + } + + ri <<= 8; + ri |= *(d++); + if (d >= end) { + d = data; + } + + ri <<= 8; + ri |= *(d++); + if (d >= end) { + d = data; + } + + p[i] ^= ri; + } + + in[0] = 0L; + in[1] = 0L; + for (i = 0; i < BF_ROUNDS + 2; i += 2) { + BF_encrypt(in, key); + p[i] = in[0]; + p[i + 1] = in[1]; + } + + p = key->S; + for (i = 0; i < 4 * 256; i += 2) { + BF_encrypt(in, key); + p[i] = in[0]; + p[i + 1] = in[1]; + } +} diff --git a/external/boringssl/decrepit/cast/CMakeLists.txt b/external/boringssl/decrepit/cast/CMakeLists.txt new file mode 100644 index 0000000000..2830381a6d --- /dev/null +++ b/external/boringssl/decrepit/cast/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(../../include) + +add_library( + cast + + OBJECT + + cast.c + cast_tables.c +) diff --git a/external/boringssl/decrepit/cast/cast.c b/external/boringssl/decrepit/cast/cast.c new file mode 100644 index 0000000000..75ea656717 --- /dev/null +++ b/external/boringssl/decrepit/cast/cast.c @@ -0,0 +1,408 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.]. */ + +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include "internal.h" +#include "../macros.h" + + +void CAST_ecb_encrypt(const uint8_t *in, uint8_t *out, const CAST_KEY *ks, + int enc) { + uint32_t d[2]; + + n2l(in, d[0]); + n2l(in, d[1]); + if (enc) { + CAST_encrypt(d, ks); + } else { + CAST_decrypt(d, ks); + } + l2n(d[0], out); + l2n(d[1], out); +} + +#if defined(OPENSSL_WINDOWS) && defined(_MSC_VER) +#define ROTL(a, n) (_lrotl(a, n)) +#else +#define ROTL(a, n) ((((a) << (n)) | ((a) >> ((-(n))&31))) & 0xffffffffL) +#endif + +#define E_CAST(n, key, L, R, OP1, OP2, OP3) \ + { \ + uint32_t a, b, c, d; \ + t = (key[n * 2] OP1 R) & 0xffffffff; \ + t = ROTL(t, (key[n * 2 + 1])); \ + a = CAST_S_table0[(t >> 8) & 0xff]; \ + b = CAST_S_table1[(t)&0xff]; \ + c = CAST_S_table2[(t >> 24) & 0xff]; \ + d = CAST_S_table3[(t >> 16) & 0xff]; \ + L ^= (((((a OP2 b)&0xffffffffL)OP3 c) & 0xffffffffL)OP1 d) & 0xffffffffL; \ + } + +void CAST_encrypt(uint32_t *data, const CAST_KEY *key) { + uint32_t l, r, t; + const uint32_t *k; + + k = &key->data[0]; + l = data[0]; + r = data[1]; + + E_CAST(0, k, l, r, +, ^, -); + E_CAST(1, k, r, l, ^, -, +); + E_CAST(2, k, l, r, -, +, ^); + E_CAST(3, k, r, l, +, ^, -); + E_CAST(4, k, l, r, ^, -, +); + E_CAST(5, k, r, l, -, +, ^); + E_CAST(6, k, l, r, +, ^, -); + E_CAST(7, k, r, l, ^, -, +); + E_CAST(8, k, l, r, -, +, ^); + E_CAST(9, k, r, l, +, ^, -); + E_CAST(10, k, l, r, ^, -, +); + E_CAST(11, k, r, l, -, +, ^); + + if (!key->short_key) { + E_CAST(12, k, l, r, +, ^, -); + E_CAST(13, k, r, l, ^, -, +); + E_CAST(14, k, l, r, -, +, ^); + E_CAST(15, k, r, l, +, ^, -); + } + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void CAST_decrypt(uint32_t *data, const CAST_KEY *key) { + uint32_t l, r, t; + const uint32_t *k; + + k = &key->data[0]; + l = data[0]; + r = data[1]; + + if (!key->short_key) { + E_CAST(15, k, l, r, +, ^, -); + E_CAST(14, k, r, l, -, +, ^); + E_CAST(13, k, l, r, ^, -, +); + E_CAST(12, k, r, l, +, ^, -); + } + + E_CAST(11, k, l, r, -, +, ^); + E_CAST(10, k, r, l, ^, -, +); + E_CAST(9, k, l, r, +, ^, -); + E_CAST(8, k, r, l, -, +, ^); + E_CAST(7, k, l, r, ^, -, +); + E_CAST(6, k, r, l, +, ^, -); + E_CAST(5, k, l, r, -, +, ^); + E_CAST(4, k, r, l, ^, -, +); + E_CAST(3, k, l, r, +, ^, -); + E_CAST(2, k, r, l, -, +, ^); + E_CAST(1, k, l, r, ^, -, +); + E_CAST(0, k, r, l, +, ^, -); + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void CAST_cbc_encrypt(const uint8_t *in, uint8_t *out, long length, + const CAST_KEY *ks, uint8_t *iv, int enc) { + uint32_t tin0, tin1; + uint32_t tout0, tout1, xor0, xor1; + long l = length; + uint32_t tin[2]; + + if (enc) { + n2l(iv, tout0); + n2l(iv, tout1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + CAST_encrypt(tin, ks); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + if (l != -8) { + n2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + CAST_encrypt(tin, ks); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + l2n(tout0, iv); + l2n(tout1, iv); + } else { + n2l(iv, xor0); + n2l(iv, xor1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + CAST_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2n(tout0, out); + l2n(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + CAST_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2nn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2n(xor0, iv); + l2n(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +#define CAST_exp(l, A, a, n) \ + A[n / 4] = l; \ + a[n + 3] = (l)&0xff; \ + a[n + 2] = (l >> 8) & 0xff; \ + a[n + 1] = (l >> 16) & 0xff; \ + a[n + 0] = (l >> 24) & 0xff; +#define S4 CAST_S_table4 +#define S5 CAST_S_table5 +#define S6 CAST_S_table6 +#define S7 CAST_S_table7 + +void CAST_set_key(CAST_KEY *key, size_t len, const uint8_t *data) { + uint32_t x[16]; + uint32_t z[16]; + uint32_t k[32]; + uint32_t X[4], Z[4]; + uint32_t l, *K; + size_t i; + + for (i = 0; i < 16; i++) { + x[i] = 0; + } + + if (len > 16) { + len = 16; + } + + for (i = 0; i < len; i++) { + x[i] = data[i]; + } + + if (len <= 10) { + key->short_key = 1; + } else { + key->short_key = 0; + } + + K = &k[0]; + X[0] = ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3]) & 0xffffffffL; + X[1] = ((x[4] << 24) | (x[5] << 16) | (x[6] << 8) | x[7]) & 0xffffffffL; + X[2] = ((x[8] << 24) | (x[9] << 16) | (x[10] << 8) | x[11]) & 0xffffffffL; + X[3] = ((x[12] << 24) | (x[13] << 16) | (x[14] << 8) | x[15]) & 0xffffffffL; + + for (;;) { + l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]]; + CAST_exp(l, Z, z, 0); + l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]]; + CAST_exp(l, Z, z, 4); + l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]]; + CAST_exp(l, Z, z, 8); + l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]]; + CAST_exp(l, Z, z, 12); + + K[0] = S4[z[8]] ^ S5[z[9]] ^ S6[z[7]] ^ S7[z[6]] ^ S4[z[2]]; + K[1] = S4[z[10]] ^ S5[z[11]] ^ S6[z[5]] ^ S7[z[4]] ^ S5[z[6]]; + K[2] = S4[z[12]] ^ S5[z[13]] ^ S6[z[3]] ^ S7[z[2]] ^ S6[z[9]]; + K[3] = S4[z[14]] ^ S5[z[15]] ^ S6[z[1]] ^ S7[z[0]] ^ S7[z[12]]; + + l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]]; + CAST_exp(l, X, x, 0); + l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]]; + CAST_exp(l, X, x, 4); + l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]]; + CAST_exp(l, X, x, 8); + l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]]; + CAST_exp(l, X, x, 12); + + K[4] = S4[x[3]] ^ S5[x[2]] ^ S6[x[12]] ^ S7[x[13]] ^ S4[x[8]]; + K[5] = S4[x[1]] ^ S5[x[0]] ^ S6[x[14]] ^ S7[x[15]] ^ S5[x[13]]; + K[6] = S4[x[7]] ^ S5[x[6]] ^ S6[x[8]] ^ S7[x[9]] ^ S6[x[3]]; + K[7] = S4[x[5]] ^ S5[x[4]] ^ S6[x[10]] ^ S7[x[11]] ^ S7[x[7]]; + + l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]]; + CAST_exp(l, Z, z, 0); + l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]]; + CAST_exp(l, Z, z, 4); + l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]]; + CAST_exp(l, Z, z, 8); + l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]]; + CAST_exp(l, Z, z, 12); + + K[8] = S4[z[3]] ^ S5[z[2]] ^ S6[z[12]] ^ S7[z[13]] ^ S4[z[9]]; + K[9] = S4[z[1]] ^ S5[z[0]] ^ S6[z[14]] ^ S7[z[15]] ^ S5[z[12]]; + K[10] = S4[z[7]] ^ S5[z[6]] ^ S6[z[8]] ^ S7[z[9]] ^ S6[z[2]]; + K[11] = S4[z[5]] ^ S5[z[4]] ^ S6[z[10]] ^ S7[z[11]] ^ S7[z[6]]; + + l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]]; + CAST_exp(l, X, x, 0); + l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]]; + CAST_exp(l, X, x, 4); + l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]]; + CAST_exp(l, X, x, 8); + l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]]; + CAST_exp(l, X, x, 12); + + K[12] = S4[x[8]] ^ S5[x[9]] ^ S6[x[7]] ^ S7[x[6]] ^ S4[x[3]]; + K[13] = S4[x[10]] ^ S5[x[11]] ^ S6[x[5]] ^ S7[x[4]] ^ S5[x[7]]; + K[14] = S4[x[12]] ^ S5[x[13]] ^ S6[x[3]] ^ S7[x[2]] ^ S6[x[8]]; + K[15] = S4[x[14]] ^ S5[x[15]] ^ S6[x[1]] ^ S7[x[0]] ^ S7[x[13]]; + if (K != k) { + break; + } + K += 16; + } + + for (i = 0; i < 16; i++) { + key->data[i * 2] = k[i]; + key->data[i * 2 + 1] = ((k[i + 16]) + 16) & 0x1f; + } +} + +/* The input and output encrypted as though 64bit cfb mode is being used. The + * extra state information to record how much of the 64bit block we have used + * is contained in *num. */ +void CAST_cfb64_encrypt(const uint8_t *in, uint8_t *out, long length, + const CAST_KEY *schedule, uint8_t *ivec, int *num, + int enc) { + uint32_t v0, v1, t; + int n = *num; + long l = length; + uint32_t ti[2]; + uint8_t *iv, c, cc; + + iv = ivec; + if (enc) { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + CAST_encrypt((uint32_t *)ti, schedule); + iv = ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = ivec; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + CAST_encrypt((uint32_t *)ti, schedule); + iv = ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = ivec; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = t = c = cc = 0; + *num = n; +} diff --git a/external/boringssl/decrepit/cast/cast_tables.c b/external/boringssl/decrepit/cast/cast_tables.c new file mode 100644 index 0000000000..6808aa894b --- /dev/null +++ b/external/boringssl/decrepit/cast/cast_tables.c @@ -0,0 +1,428 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include "internal.h" + + +const uint32_t CAST_S_table0[256] = { + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, + 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, + 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, + 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, + 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, + 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, + 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, + 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, + 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, + 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, + 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, + 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, + 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, + 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, + 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, + 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, + 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, + 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, + 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, + 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, + 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, + 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, + 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, + 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, + 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, + 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, + 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, + 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, + 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, + 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, + 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, + 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, + 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, +}; + +const uint32_t CAST_S_table1[256] = { + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, + 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, + 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, + 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, + 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, + 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, + 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, + 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, + 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, + 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, + 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, + 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, + 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, + 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, + 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, + 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, + 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, + 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, + 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, + 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, + 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, + 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, + 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, + 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, + 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, + 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, + 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, + 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, + 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, + 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, + 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, + 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, + 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, +}; + +const uint32_t CAST_S_table2[256] = { + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, + 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, + 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, + 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, + 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, + 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, + 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, + 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, + 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, + 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, + 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, + 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, + 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, + 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, + 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, + 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, + 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, + 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, + 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, + 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, + 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, + 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, + 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, + 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, + 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, + 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, + 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, + 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, + 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, + 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, + 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, + 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, + 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, +}; + +const uint32_t CAST_S_table3[256] = { + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, + 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, + 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, + 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, + 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, + 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, + 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, + 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, + 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, + 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, + 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, + 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, + 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, + 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, + 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, + 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, + 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, + 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, + 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, + 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, + 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, + 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, + 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, + 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, + 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, + 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, + 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, + 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, + 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, + 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, + 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, + 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, + 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, +}; + +const uint32_t CAST_S_table4[256] = { + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, + 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, + 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, + 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, + 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, + 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, + 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, + 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, + 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, + 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, + 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, + 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, + 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, + 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, + 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, + 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, + 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, + 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, + 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, + 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, + 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, + 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, + 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, + 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, + 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, + 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, + 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, + 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, + 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, + 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, + 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, + 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, + 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, +}; + +const uint32_t CAST_S_table5[256] = { + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, + 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, + 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, + 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, + 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, + 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, + 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, + 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, + 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, + 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, + 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, + 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, + 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, + 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, + 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, + 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, + 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, + 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, + 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, + 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, + 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, + 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, + 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, + 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, + 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, + 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, + 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, + 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, + 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, + 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, + 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, + 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, + 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, +}; + +const uint32_t CAST_S_table6[256] = { + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, + 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, + 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, + 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, + 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, + 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, + 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, + 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, + 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, + 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, + 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, + 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, + 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, + 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, + 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, + 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, + 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, + 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, + 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, + 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, + 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, + 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, + 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, + 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, + 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, + 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, + 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, + 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, + 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, + 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, + 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, + 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, + 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, +}; + +const uint32_t CAST_S_table7[256] = { + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, + 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, + 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, + 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, + 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, + 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, + 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, + 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, + 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, + 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, + 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, + 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, + 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, + 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, + 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, + 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, + 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, + 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, + 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, + 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, + 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, + 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, + 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, + 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, + 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, + 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, + 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, + 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, + 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, + 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, + 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, + 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, + 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, +}; diff --git a/external/boringssl/decrepit/cast/internal.h b/external/boringssl/decrepit/cast/internal.h new file mode 100644 index 0000000000..15e222264c --- /dev/null +++ b/external/boringssl/decrepit/cast/internal.h @@ -0,0 +1,81 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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_CAST_INTERNAL_H +#define OPENSSL_HEADER_CAST_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +extern const uint32_t CAST_S_table0[256]; +extern const uint32_t CAST_S_table1[256]; +extern const uint32_t CAST_S_table2[256]; +extern const uint32_t CAST_S_table3[256]; +extern const uint32_t CAST_S_table4[256]; +extern const uint32_t CAST_S_table5[256]; +extern const uint32_t CAST_S_table6[256]; +extern const uint32_t CAST_S_table7[256]; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CAST_INTERNAL_H */ diff --git a/external/boringssl/decrepit/des/CMakeLists.txt b/external/boringssl/decrepit/des/CMakeLists.txt new file mode 100644 index 0000000000..0ee5c2e3b5 --- /dev/null +++ b/external/boringssl/decrepit/des/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + des_decrepit + + OBJECT + + cfb64ede.c +) diff --git a/external/boringssl/decrepit/des/cfb64ede.c b/external/boringssl/decrepit/des/cfb64ede.c new file mode 100644 index 0000000000..f7e81d4557 --- /dev/null +++ b/external/boringssl/decrepit/des/cfb64ede.c @@ -0,0 +1,236 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "../crypto/des/internal.h" + + +/* The input and output encrypted as though 64bit cfb mode is being used. The + * extra state information to record how much of the 64bit block we have used + * is contained in *num; */ +void DES_ede3_cfb64_encrypt(const uint8_t *in, uint8_t *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc) { + uint32_t v0, v1; + long l = length; + int n = *num; + uint32_t ti[2]; + uint8_t *iv, c, cc; + + iv = ivec->bytes; + if (enc) { + while (l--) { + if (n == 0) { + c2l(iv, v0); + c2l(iv, v1); + + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + v0 = ti[0]; + v1 = ti[1]; + + iv = ivec->bytes; + l2c(v0, iv); + l2c(v1, iv); + iv = ivec->bytes; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + c2l(iv, v0); + c2l(iv, v1); + + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + v0 = ti[0]; + v1 = ti[1]; + + iv = ivec->bytes; + l2c(v0, iv); + l2c(v1, iv); + iv = ivec->bytes; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = c = cc = 0; + *num = n; +} + +/* This is compatible with the single key CFB-r for DES, even thought that's + * not what EVP needs. */ + +void DES_ede3_cfb_encrypt(const uint8_t *in, uint8_t *out, int numbits, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc) { + uint32_t d0, d1, v0, v1; + unsigned long l = length, n = ((unsigned int)numbits + 7) / 8; + int num = numbits, i; + uint32_t ti[2]; + uint8_t *iv; + uint8_t ovec[16]; + + if (num > 64) { + return; + }; + + iv = ivec->bytes; + c2l(iv, v0); + c2l(iv, v1); + + if (enc) { + while (l >= n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + c2ln(in, d0, d1, n); + in += n; + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + /* 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( */ + if (num == 32) { + v0 = v1; + v1 = d0; + } else if (num == 64) { + v0 = d0; + v1 = d1; + } else { + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); + /* shift ovec left most of the bits... */ + memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0)); + /* now the remaining bits */ + if (num % 8 != 0) { + for (i = 0; i < 8; ++i) { + ovec[i] <<= num % 8; + ovec[i] |= ovec[i + 1] >> (8 - num % 8); + } + } + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); + } + } + } else { + while (l >= n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + c2ln(in, d0, d1, n); + in += n; + /* 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( */ + if (num == 32) { + v0 = v1; + v1 = d0; + } else if (num == 64) { + v0 = d0; + v1 = d1; + } else { + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); + /* shift ovec left most of the bits... */ + memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0)); + /* now the remaining bits */ + if (num % 8 != 0) { + for (i = 0; i < 8; ++i) { + ovec[i] <<= num % 8; + ovec[i] |= ovec[i + 1] >> (8 - num % 8); + } + } + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); + } + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + } + } + + iv = ivec->bytes; + l2c(v0, iv); + l2c(v1, iv); + v0 = v1 = d0 = d1 = ti[0] = ti[1] = 0; +} diff --git a/external/boringssl/decrepit/dh/CMakeLists.txt b/external/boringssl/decrepit/dh/CMakeLists.txt new file mode 100644 index 0000000000..fb862b512b --- /dev/null +++ b/external/boringssl/decrepit/dh/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + dh_decrepit + + OBJECT + + dh_decrepit.c +) diff --git a/external/boringssl/decrepit/dh/dh_decrepit.c b/external/boringssl/decrepit/dh/dh_decrepit.c new file mode 100644 index 0000000000..1d38c12eb4 --- /dev/null +++ b/external/boringssl/decrepit/dh/dh_decrepit.c @@ -0,0 +1,103 @@ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + + +struct wrapped_callback { + void (*callback)(int, int, void *); + void *arg; +}; + +/* callback_wrapper converts an “old†style generation callback to the newer + * |BN_GENCB| form. */ +static int callback_wrapper(int event, int n, BN_GENCB *gencb) { + struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg; + wrapped->callback(event, n, wrapped->arg); + return 1; +} + +DH *DH_generate_parameters(int prime_len, int generator, + void (*callback)(int, int, void *), void *cb_arg) { + if (prime_len < 0 || generator < 0) { + return NULL; + } + + DH *ret = DH_new(); + if (ret == NULL) { + return NULL; + } + + BN_GENCB gencb_storage; + BN_GENCB *cb = NULL; + + struct wrapped_callback wrapped; + + if (callback != NULL) { + wrapped.callback = callback; + wrapped.arg = cb_arg; + + cb = &gencb_storage; + BN_GENCB_set(cb, callback_wrapper, &wrapped); + } + + if (!DH_generate_parameters_ex(ret, prime_len, generator, cb)) { + goto err; + } + + return ret; + +err: + DH_free(ret); + return NULL; +} diff --git a/external/boringssl/decrepit/dsa/CMakeLists.txt b/external/boringssl/decrepit/dsa/CMakeLists.txt new file mode 100644 index 0000000000..cc64b60483 --- /dev/null +++ b/external/boringssl/decrepit/dsa/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + dsa_decrepit + + OBJECT + + dsa_decrepit.c +) diff --git a/external/boringssl/decrepit/dsa/dsa_decrepit.c b/external/boringssl/decrepit/dsa/dsa_decrepit.c new file mode 100644 index 0000000000..aef8056bf1 --- /dev/null +++ b/external/boringssl/decrepit/dsa/dsa_decrepit.c @@ -0,0 +1,105 @@ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + + +struct wrapped_callback { + void (*callback)(int, int, void *); + void *arg; +}; + +/* callback_wrapper converts an “old†style generation callback to the newer + * |BN_GENCB| form. */ +static int callback_wrapper(int event, int n, BN_GENCB *gencb) { + struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg; + wrapped->callback(event, n, wrapped->arg); + return 1; +} + +DSA *DSA_generate_parameters(int bits, uint8_t *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + void (*callback)(int, int, void *), void *cb_arg) { + if (bits < 0 || seed_len < 0) { + return NULL; + } + + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + + BN_GENCB gencb_storage; + BN_GENCB *cb = NULL; + + struct wrapped_callback wrapped; + + if (callback != NULL) { + wrapped.callback = callback; + wrapped.arg = cb_arg; + + cb = &gencb_storage; + BN_GENCB_set(cb, callback_wrapper, &wrapped); + } + + if (!DSA_generate_parameters_ex(ret, bits, seed_in, seed_len, counter_ret, + h_ret, cb)) { + goto err; + } + + return ret; + +err: + DSA_free(ret); + return NULL; +} diff --git a/external/boringssl/decrepit/evp/CMakeLists.txt b/external/boringssl/decrepit/evp/CMakeLists.txt new file mode 100644 index 0000000000..e631a9a99f --- /dev/null +++ b/external/boringssl/decrepit/evp/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(../../include) + +add_library( + evp_decrepit + + OBJECT + + dss1.c + evp_do_all.c +) diff --git a/external/boringssl/decrepit/evp/dss1.c b/external/boringssl/decrepit/evp/dss1.c new file mode 100644 index 0000000000..9c370acb77 --- /dev/null +++ b/external/boringssl/decrepit/evp/dss1.c @@ -0,0 +1,20 @@ +/* Copyright (c) 2016, 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 + + +const EVP_MD *EVP_dss1(void) { + return EVP_sha1(); +} diff --git a/external/boringssl/decrepit/evp/evp_do_all.c b/external/boringssl/decrepit/evp/evp_do_all.c new file mode 100644 index 0000000000..621c0b1170 --- /dev/null +++ b/external/boringssl/decrepit/evp/evp_do_all.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2016, 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 + + +void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher, + const char *name, + const char *unused, void *arg), + void *arg) { + callback(EVP_aes_128_cbc(), "AES-128-CBC", NULL, arg); + callback(EVP_aes_128_ctr(), "AES-128-CTR", NULL, arg); + callback(EVP_aes_128_ecb(), "AES-128-ECB", NULL, arg); + callback(EVP_aes_128_ofb(), "AES-128-OFB", NULL, arg); + callback(EVP_aes_256_cbc(), "AES-256-CBC", NULL, arg); + callback(EVP_aes_256_ctr(), "AES-256-CTR", NULL, arg); + callback(EVP_aes_256_ecb(), "AES-256-ECB", NULL, arg); + callback(EVP_aes_256_ofb(), "AES-256-OFB", NULL, arg); + callback(EVP_aes_256_xts(), "AES-256-XTS", NULL, arg); + callback(EVP_des_cbc(), "DES-CBC", NULL, arg); + callback(EVP_des_ecb(), "DES-ECB", NULL, arg); + callback(EVP_des_ede(), "DES-EDE", NULL, arg); + callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg); + callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg); + callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg); + callback(EVP_rc4(), "RC4", NULL, arg); + + /* OpenSSL returns everything twice, the second time in lower case. */ + callback(EVP_aes_128_cbc(), "aes-128-cbc", NULL, arg); + callback(EVP_aes_128_ctr(), "aes-128-ctr", NULL, arg); + callback(EVP_aes_128_ecb(), "aes-128-ecb", NULL, arg); + callback(EVP_aes_128_ofb(), "aes-128-ofb", NULL, arg); + callback(EVP_aes_256_cbc(), "aes-256-cbc", NULL, arg); + callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg); + callback(EVP_aes_256_ecb(), "aes-256-ecb", NULL, arg); + callback(EVP_aes_256_ofb(), "aes-256-ofb", NULL, arg); + callback(EVP_aes_256_xts(), "aes-256-xts", NULL, arg); + callback(EVP_des_cbc(), "des-cbc", NULL, arg); + callback(EVP_des_ecb(), "des-ecb", NULL, arg); + callback(EVP_des_ede(), "des-ede", NULL, arg); + callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg); + callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg); + callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg); + callback(EVP_rc4(), "rc4", NULL, arg); +} + +void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher, + const char *name, const char *unused, + void *arg), + void *arg) { + callback(EVP_md4(), "MD4", NULL, arg); + callback(EVP_md5(), "MD5", NULL, arg); + callback(EVP_sha1(), "SHA1", NULL, arg); + callback(EVP_sha224(), "SHA224", NULL, arg); + callback(EVP_sha256(), "SHA256", NULL, arg); + callback(EVP_sha384(), "SHA384", NULL, arg); + callback(EVP_sha512(), "SHA512", NULL, arg); + + callback(EVP_md4(), "md4", NULL, arg); + callback(EVP_md5(), "md5", NULL, arg); + callback(EVP_sha1(), "sha1", NULL, arg); + callback(EVP_sha224(), "sha224", NULL, arg); + callback(EVP_sha256(), "sha256", NULL, arg); + callback(EVP_sha384(), "sha384", NULL, arg); + callback(EVP_sha512(), "sha512", NULL, arg); +} diff --git a/external/boringssl/decrepit/macros.h b/external/boringssl/decrepit/macros.h new file mode 100644 index 0000000000..228183a332 --- /dev/null +++ b/external/boringssl/decrepit/macros.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_DECREPIT_MACROS_H +#define OPENSSL_HEADER_DECREPIT_MACROS_H + + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c, l1, l2, n) \ + { \ + c += n; \ + l1 = l2 = 0; \ + switch (n) { \ + case 8: \ + l2 = ((unsigned long)(*(--(c)))); \ + case 7: \ + l2 |= ((unsigned long)(*(--(c)))) << 8; \ + case 6: \ + l2 |= ((unsigned long)(*(--(c)))) << 16; \ + case 5: \ + l2 |= ((unsigned long)(*(--(c)))) << 24; \ + case 4: \ + l1 = ((unsigned long)(*(--(c)))); \ + case 3: \ + l1 |= ((unsigned long)(*(--(c)))) << 8; \ + case 2: \ + l1 |= ((unsigned long)(*(--(c)))) << 16; \ + case 1: \ + l1 |= ((unsigned long)(*(--(c)))) << 24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1, l2, c, n) \ + { \ + c += n; \ + switch (n) { \ + case 8: \ + *(--(c)) = (unsigned char)(((l2)) & 0xff); \ + case 7: \ + *(--(c)) = (unsigned char)(((l2) >> 8) & 0xff); \ + case 6: \ + *(--(c)) = (unsigned char)(((l2) >> 16) & 0xff); \ + case 5: \ + *(--(c)) = (unsigned char)(((l2) >> 24) & 0xff); \ + case 4: \ + *(--(c)) = (unsigned char)(((l1)) & 0xff); \ + case 3: \ + *(--(c)) = (unsigned char)(((l1) >> 8) & 0xff); \ + case 2: \ + *(--(c)) = (unsigned char)(((l1) >> 16) & 0xff); \ + case 1: \ + *(--(c)) = (unsigned char)(((l1) >> 24) & 0xff); \ + } \ + } + +#define l2n(l, c) \ + (*((c)++) = (unsigned char)(((l) >> 24L) & 0xff), \ + *((c)++) = (unsigned char)(((l) >> 16L) & 0xff), \ + *((c)++) = (unsigned char)(((l) >> 8L) & 0xff), \ + *((c)++) = (unsigned char)(((l)) & 0xff)) + +#define n2l(c, l) \ + (l = ((unsigned long)(*((c)++))) << 24L, \ + l |= ((unsigned long)(*((c)++))) << 16L, \ + l |= ((unsigned long)(*((c)++))) << 8L, \ + l |= ((unsigned long)(*((c)++)))) + + +#endif /* OPENSSL_HEADER_DECREPIT_MACROS_H */ diff --git a/external/boringssl/decrepit/obj/CMakeLists.txt b/external/boringssl/decrepit/obj/CMakeLists.txt new file mode 100644 index 0000000000..caaecd32c8 --- /dev/null +++ b/external/boringssl/decrepit/obj/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + obj_decrepit + + OBJECT + + obj_decrepit.c +) diff --git a/external/boringssl/decrepit/obj/obj_decrepit.c b/external/boringssl/decrepit/obj/obj_decrepit.c new file mode 100644 index 0000000000..06051f1124 --- /dev/null +++ b/external/boringssl/decrepit/obj/obj_decrepit.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include + + +struct wrapped_callback { + void (*callback)(const OBJ_NAME *, void *arg); + void *arg; +}; + +static void cipher_callback(const EVP_CIPHER *cipher, const char *name, + const char *unused, void *arg) { + const struct wrapped_callback *wrapped = (struct wrapped_callback *)arg; + OBJ_NAME obj_name; + + memset(&obj_name, 0, sizeof(obj_name)); + obj_name.type = OBJ_NAME_TYPE_CIPHER_METH; + obj_name.name = name; + + wrapped->callback(&obj_name, wrapped->arg); +} + +static void md_callback(const EVP_MD *md, const char *name, const char *unused, + void *arg) { + const struct wrapped_callback *wrapped = (struct wrapped_callback*) arg; + OBJ_NAME obj_name; + + memset(&obj_name, 0, sizeof(obj_name)); + obj_name.type = OBJ_NAME_TYPE_MD_METH; + obj_name.name = name; + + wrapped->callback(&obj_name, wrapped->arg); +} + +void OBJ_NAME_do_all_sorted(int type, + void (*callback)(const OBJ_NAME *, void *arg), + void *arg) { + struct wrapped_callback wrapped; + wrapped.callback = callback; + wrapped.arg = arg; + + if (type == OBJ_NAME_TYPE_CIPHER_METH) { + EVP_CIPHER_do_all_sorted(cipher_callback, &wrapped); + } else if (type == OBJ_NAME_TYPE_MD_METH) { + EVP_MD_do_all_sorted(md_callback, &wrapped); + } else { + assert(0); + } +} + +void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *, void *arg), + void *arg) { + OBJ_NAME_do_all_sorted(type, callback, arg); +} diff --git a/external/boringssl/decrepit/rc4/CMakeLists.txt b/external/boringssl/decrepit/rc4/CMakeLists.txt new file mode 100644 index 0000000000..459b24e2f7 --- /dev/null +++ b/external/boringssl/decrepit/rc4/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + rc4_decrepit + + OBJECT + + rc4_decrepit.c +) diff --git a/external/boringssl/decrepit/rc4/rc4_decrepit.c b/external/boringssl/decrepit/rc4/rc4_decrepit.c new file mode 100644 index 0000000000..140e15d612 --- /dev/null +++ b/external/boringssl/decrepit/rc4/rc4_decrepit.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + + +const char *RC4_options(void) { + return "rc4(ptr,int)"; +} diff --git a/external/boringssl/decrepit/ripemd/CMakeLists.txt b/external/boringssl/decrepit/ripemd/CMakeLists.txt new file mode 100644 index 0000000000..b913e5b848 --- /dev/null +++ b/external/boringssl/decrepit/ripemd/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + ripemd_decrepit + + OBJECT + + ripemd.c +) + +if(ENABLE_TESTS) +add_executable( + ripemd_test + + ripemd_test.cc + + $ +) + +target_link_libraries(ripemd_test crypto) +target_link_libraries(ripemd_test decrepit) +add_dependencies(all_tests ripemd_test) +endif() diff --git a/external/boringssl/decrepit/ripemd/internal.h b/external/boringssl/decrepit/ripemd/internal.h new file mode 100644 index 0000000000..c4db4b23dd --- /dev/null +++ b/external/boringssl/decrepit/ripemd/internal.h @@ -0,0 +1,493 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of 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_BN_INTERNAL_H +#define OPENSSL_HEADER_BN_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data, + size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG uint32_t +#define HASH_CTX RIPEMD160_CTX +#define HASH_CBLOCK RIPEMD160_CBLOCK +#define HASH_UPDATE RIPEMD160_Update +#define HASH_TRANSFORM RIPEMD160_Transform +#define HASH_FINAL RIPEMD160_Final +#define HASH_MAKE_STRING(c, s) \ + do { \ + unsigned long ll; \ + ll = (c)->h[0]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[4]; \ + (void)HOST_l2c(ll, (s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order + +#include "../../crypto/digest/md32_common.h" + +/* Transformed F2 and F4 are courtesy of Wei Dai */ +#define F1(x, y, z) ((x) ^ (y) ^ (z)) +#define F2(x, y, z) ((((y) ^ (z)) & (x)) ^ (z)) +#define F3(x, y, z) (((~(y)) | (x)) ^ (z)) +#define F4(x, y, z) ((((x) ^ (y)) & (z)) ^ (y)) +#define F5(x, y, z) (((~(z)) | (y)) ^ (x)) + +#define RIPEMD160_A 0x67452301L +#define RIPEMD160_B 0xEFCDAB89L +#define RIPEMD160_C 0x98BADCFEL +#define RIPEMD160_D 0x10325476L +#define RIPEMD160_E 0xC3D2E1F0L + +#define ROTATE(a, n) (((a) << (n)) | (((a)&0xffffffff) >> (32 - (n)))) + +#define RIP1(a, b, c, d, e, w, s) \ + { \ + a += F1(b, c, d) + X(w); \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP2(a, b, c, d, e, w, s, K) \ + { \ + a += F2(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP3(a, b, c, d, e, w, s, K) \ + { \ + a += F3(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP4(a, b, c, d, e, w, s, K) \ + { \ + a += F4(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP5(a, b, c, d, e, w, s, K) \ + { \ + a += F5(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define KL0 0x00000000L +#define KL1 0x5A827999L +#define KL2 0x6ED9EBA1L +#define KL3 0x8F1BBCDCL +#define KL4 0xA953FD4EL + +#define KR0 0x50A28BE6L +#define KR1 0x5C4DD124L +#define KR2 0x6D703EF3L +#define KR3 0x7A6D76E9L +#define KR4 0x00000000L + +#define WL00 0 +#define SL00 11 +#define WL01 1 +#define SL01 14 +#define WL02 2 +#define SL02 15 +#define WL03 3 +#define SL03 12 +#define WL04 4 +#define SL04 5 +#define WL05 5 +#define SL05 8 +#define WL06 6 +#define SL06 7 +#define WL07 7 +#define SL07 9 +#define WL08 8 +#define SL08 11 +#define WL09 9 +#define SL09 13 +#define WL10 10 +#define SL10 14 +#define WL11 11 +#define SL11 15 +#define WL12 12 +#define SL12 6 +#define WL13 13 +#define SL13 7 +#define WL14 14 +#define SL14 9 +#define WL15 15 +#define SL15 8 + +#define WL16 7 +#define SL16 7 +#define WL17 4 +#define SL17 6 +#define WL18 13 +#define SL18 8 +#define WL19 1 +#define SL19 13 +#define WL20 10 +#define SL20 11 +#define WL21 6 +#define SL21 9 +#define WL22 15 +#define SL22 7 +#define WL23 3 +#define SL23 15 +#define WL24 12 +#define SL24 7 +#define WL25 0 +#define SL25 12 +#define WL26 9 +#define SL26 15 +#define WL27 5 +#define SL27 9 +#define WL28 2 +#define SL28 11 +#define WL29 14 +#define SL29 7 +#define WL30 11 +#define SL30 13 +#define WL31 8 +#define SL31 12 + +#define WL32 3 +#define SL32 11 +#define WL33 10 +#define SL33 13 +#define WL34 14 +#define SL34 6 +#define WL35 4 +#define SL35 7 +#define WL36 9 +#define SL36 14 +#define WL37 15 +#define SL37 9 +#define WL38 8 +#define SL38 13 +#define WL39 1 +#define SL39 15 +#define WL40 2 +#define SL40 14 +#define WL41 7 +#define SL41 8 +#define WL42 0 +#define SL42 13 +#define WL43 6 +#define SL43 6 +#define WL44 13 +#define SL44 5 +#define WL45 11 +#define SL45 12 +#define WL46 5 +#define SL46 7 +#define WL47 12 +#define SL47 5 + +#define WL48 1 +#define SL48 11 +#define WL49 9 +#define SL49 12 +#define WL50 11 +#define SL50 14 +#define WL51 10 +#define SL51 15 +#define WL52 0 +#define SL52 14 +#define WL53 8 +#define SL53 15 +#define WL54 12 +#define SL54 9 +#define WL55 4 +#define SL55 8 +#define WL56 13 +#define SL56 9 +#define WL57 3 +#define SL57 14 +#define WL58 7 +#define SL58 5 +#define WL59 15 +#define SL59 6 +#define WL60 14 +#define SL60 8 +#define WL61 5 +#define SL61 6 +#define WL62 6 +#define SL62 5 +#define WL63 2 +#define SL63 12 + +#define WL64 4 +#define SL64 9 +#define WL65 0 +#define SL65 15 +#define WL66 5 +#define SL66 5 +#define WL67 9 +#define SL67 11 +#define WL68 7 +#define SL68 6 +#define WL69 12 +#define SL69 8 +#define WL70 2 +#define SL70 13 +#define WL71 10 +#define SL71 12 +#define WL72 14 +#define SL72 5 +#define WL73 1 +#define SL73 12 +#define WL74 3 +#define SL74 13 +#define WL75 8 +#define SL75 14 +#define WL76 11 +#define SL76 11 +#define WL77 6 +#define SL77 8 +#define WL78 15 +#define SL78 5 +#define WL79 13 +#define SL79 6 + +#define WR00 5 +#define SR00 8 +#define WR01 14 +#define SR01 9 +#define WR02 7 +#define SR02 9 +#define WR03 0 +#define SR03 11 +#define WR04 9 +#define SR04 13 +#define WR05 2 +#define SR05 15 +#define WR06 11 +#define SR06 15 +#define WR07 4 +#define SR07 5 +#define WR08 13 +#define SR08 7 +#define WR09 6 +#define SR09 7 +#define WR10 15 +#define SR10 8 +#define WR11 8 +#define SR11 11 +#define WR12 1 +#define SR12 14 +#define WR13 10 +#define SR13 14 +#define WR14 3 +#define SR14 12 +#define WR15 12 +#define SR15 6 + +#define WR16 6 +#define SR16 9 +#define WR17 11 +#define SR17 13 +#define WR18 3 +#define SR18 15 +#define WR19 7 +#define SR19 7 +#define WR20 0 +#define SR20 12 +#define WR21 13 +#define SR21 8 +#define WR22 5 +#define SR22 9 +#define WR23 10 +#define SR23 11 +#define WR24 14 +#define SR24 7 +#define WR25 15 +#define SR25 7 +#define WR26 8 +#define SR26 12 +#define WR27 12 +#define SR27 7 +#define WR28 4 +#define SR28 6 +#define WR29 9 +#define SR29 15 +#define WR30 1 +#define SR30 13 +#define WR31 2 +#define SR31 11 + +#define WR32 15 +#define SR32 9 +#define WR33 5 +#define SR33 7 +#define WR34 1 +#define SR34 15 +#define WR35 3 +#define SR35 11 +#define WR36 7 +#define SR36 8 +#define WR37 14 +#define SR37 6 +#define WR38 6 +#define SR38 6 +#define WR39 9 +#define SR39 14 +#define WR40 11 +#define SR40 12 +#define WR41 8 +#define SR41 13 +#define WR42 12 +#define SR42 5 +#define WR43 2 +#define SR43 14 +#define WR44 10 +#define SR44 13 +#define WR45 0 +#define SR45 13 +#define WR46 4 +#define SR46 7 +#define WR47 13 +#define SR47 5 + +#define WR48 8 +#define SR48 15 +#define WR49 6 +#define SR49 5 +#define WR50 4 +#define SR50 8 +#define WR51 1 +#define SR51 11 +#define WR52 3 +#define SR52 14 +#define WR53 11 +#define SR53 14 +#define WR54 15 +#define SR54 6 +#define WR55 0 +#define SR55 14 +#define WR56 5 +#define SR56 6 +#define WR57 12 +#define SR57 9 +#define WR58 2 +#define SR58 12 +#define WR59 13 +#define SR59 9 +#define WR60 9 +#define SR60 12 +#define WR61 7 +#define SR61 5 +#define WR62 10 +#define SR62 15 +#define WR63 14 +#define SR63 8 + +#define WR64 12 +#define SR64 8 +#define WR65 15 +#define SR65 5 +#define WR66 10 +#define SR66 12 +#define WR67 4 +#define SR67 9 +#define WR68 1 +#define SR68 12 +#define WR69 5 +#define SR69 5 +#define WR70 8 +#define SR70 14 +#define WR71 7 +#define SR71 6 +#define WR72 6 +#define SR72 8 +#define WR73 2 +#define SR73 13 +#define WR74 13 +#define SR74 6 +#define WR75 14 +#define SR75 5 +#define WR76 0 +#define SR76 15 +#define WR77 3 +#define SR77 13 +#define WR78 9 +#define SR78 11 +#define WR79 11 +#define SR79 11 + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BN_INTERNAL_H */ diff --git a/external/boringssl/decrepit/ripemd/ripemd.c b/external/boringssl/decrepit/ripemd/ripemd.c new file mode 100644 index 0000000000..6ed7816c3d --- /dev/null +++ b/external/boringssl/decrepit/ripemd/ripemd.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 + +#include + +#include "internal.h" + + +int RIPEMD160_Init(RIPEMD160_CTX *ctx) { + memset(ctx, 0, sizeof(*ctx)); + ctx->h[0] = RIPEMD160_A; + ctx->h[1] = RIPEMD160_B; + ctx->h[2] = RIPEMD160_C; + ctx->h[3] = RIPEMD160_D; + ctx->h[4] = RIPEMD160_E; + return 1; +} + +static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data, + size_t num) { + uint32_t A, B, C, D, E; + uint32_t a, b, c, d, e, l; + uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12, + XX13, XX14, XX15; +#define X(i) XX##i + + for (; num--;) { + A = h[0]; + B = h[1]; + C = h[2]; + D = h[3]; + E = h[4]; + + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + RIP1(A, B, C, D, E, WL00, SL00); + (void)HOST_c2l(data, l); + X(2) = l; + RIP1(E, A, B, C, D, WL01, SL01); + (void)HOST_c2l(data, l); + X(3) = l; + RIP1(D, E, A, B, C, WL02, SL02); + (void)HOST_c2l(data, l); + X(4) = l; + RIP1(C, D, E, A, B, WL03, SL03); + (void)HOST_c2l(data, l); + X(5) = l; + RIP1(B, C, D, E, A, WL04, SL04); + (void)HOST_c2l(data, l); + X(6) = l; + RIP1(A, B, C, D, E, WL05, SL05); + (void)HOST_c2l(data, l); + X(7) = l; + RIP1(E, A, B, C, D, WL06, SL06); + (void)HOST_c2l(data, l); + X(8) = l; + RIP1(D, E, A, B, C, WL07, SL07); + (void)HOST_c2l(data, l); + X(9) = l; + RIP1(C, D, E, A, B, WL08, SL08); + (void)HOST_c2l(data, l); + X(10) = l; + RIP1(B, C, D, E, A, WL09, SL09); + (void)HOST_c2l(data, l); + X(11) = l; + RIP1(A, B, C, D, E, WL10, SL10); + (void)HOST_c2l(data, l); + X(12) = l; + RIP1(E, A, B, C, D, WL11, SL11); + (void)HOST_c2l(data, l); + X(13) = l; + RIP1(D, E, A, B, C, WL12, SL12); + (void)HOST_c2l(data, l); + X(14) = l; + RIP1(C, D, E, A, B, WL13, SL13); + (void)HOST_c2l(data, l); + X(15) = l; + RIP1(B, C, D, E, A, WL14, SL14); + RIP1(A, B, C, D, E, WL15, SL15); + + RIP2(E, A, B, C, D, WL16, SL16, KL1); + RIP2(D, E, A, B, C, WL17, SL17, KL1); + RIP2(C, D, E, A, B, WL18, SL18, KL1); + RIP2(B, C, D, E, A, WL19, SL19, KL1); + RIP2(A, B, C, D, E, WL20, SL20, KL1); + RIP2(E, A, B, C, D, WL21, SL21, KL1); + RIP2(D, E, A, B, C, WL22, SL22, KL1); + RIP2(C, D, E, A, B, WL23, SL23, KL1); + RIP2(B, C, D, E, A, WL24, SL24, KL1); + RIP2(A, B, C, D, E, WL25, SL25, KL1); + RIP2(E, A, B, C, D, WL26, SL26, KL1); + RIP2(D, E, A, B, C, WL27, SL27, KL1); + RIP2(C, D, E, A, B, WL28, SL28, KL1); + RIP2(B, C, D, E, A, WL29, SL29, KL1); + RIP2(A, B, C, D, E, WL30, SL30, KL1); + RIP2(E, A, B, C, D, WL31, SL31, KL1); + + RIP3(D, E, A, B, C, WL32, SL32, KL2); + RIP3(C, D, E, A, B, WL33, SL33, KL2); + RIP3(B, C, D, E, A, WL34, SL34, KL2); + RIP3(A, B, C, D, E, WL35, SL35, KL2); + RIP3(E, A, B, C, D, WL36, SL36, KL2); + RIP3(D, E, A, B, C, WL37, SL37, KL2); + RIP3(C, D, E, A, B, WL38, SL38, KL2); + RIP3(B, C, D, E, A, WL39, SL39, KL2); + RIP3(A, B, C, D, E, WL40, SL40, KL2); + RIP3(E, A, B, C, D, WL41, SL41, KL2); + RIP3(D, E, A, B, C, WL42, SL42, KL2); + RIP3(C, D, E, A, B, WL43, SL43, KL2); + RIP3(B, C, D, E, A, WL44, SL44, KL2); + RIP3(A, B, C, D, E, WL45, SL45, KL2); + RIP3(E, A, B, C, D, WL46, SL46, KL2); + RIP3(D, E, A, B, C, WL47, SL47, KL2); + + RIP4(C, D, E, A, B, WL48, SL48, KL3); + RIP4(B, C, D, E, A, WL49, SL49, KL3); + RIP4(A, B, C, D, E, WL50, SL50, KL3); + RIP4(E, A, B, C, D, WL51, SL51, KL3); + RIP4(D, E, A, B, C, WL52, SL52, KL3); + RIP4(C, D, E, A, B, WL53, SL53, KL3); + RIP4(B, C, D, E, A, WL54, SL54, KL3); + RIP4(A, B, C, D, E, WL55, SL55, KL3); + RIP4(E, A, B, C, D, WL56, SL56, KL3); + RIP4(D, E, A, B, C, WL57, SL57, KL3); + RIP4(C, D, E, A, B, WL58, SL58, KL3); + RIP4(B, C, D, E, A, WL59, SL59, KL3); + RIP4(A, B, C, D, E, WL60, SL60, KL3); + RIP4(E, A, B, C, D, WL61, SL61, KL3); + RIP4(D, E, A, B, C, WL62, SL62, KL3); + RIP4(C, D, E, A, B, WL63, SL63, KL3); + + RIP5(B, C, D, E, A, WL64, SL64, KL4); + RIP5(A, B, C, D, E, WL65, SL65, KL4); + RIP5(E, A, B, C, D, WL66, SL66, KL4); + RIP5(D, E, A, B, C, WL67, SL67, KL4); + RIP5(C, D, E, A, B, WL68, SL68, KL4); + RIP5(B, C, D, E, A, WL69, SL69, KL4); + RIP5(A, B, C, D, E, WL70, SL70, KL4); + RIP5(E, A, B, C, D, WL71, SL71, KL4); + RIP5(D, E, A, B, C, WL72, SL72, KL4); + RIP5(C, D, E, A, B, WL73, SL73, KL4); + RIP5(B, C, D, E, A, WL74, SL74, KL4); + RIP5(A, B, C, D, E, WL75, SL75, KL4); + RIP5(E, A, B, C, D, WL76, SL76, KL4); + RIP5(D, E, A, B, C, WL77, SL77, KL4); + RIP5(C, D, E, A, B, WL78, SL78, KL4); + RIP5(B, C, D, E, A, WL79, SL79, KL4); + + a = A; + b = B; + c = C; + d = D; + e = E; + /* Do other half */ + A = h[0]; + B = h[1]; + C = h[2]; + D = h[3]; + E = h[4]; + + RIP5(A, B, C, D, E, WR00, SR00, KR0); + RIP5(E, A, B, C, D, WR01, SR01, KR0); + RIP5(D, E, A, B, C, WR02, SR02, KR0); + RIP5(C, D, E, A, B, WR03, SR03, KR0); + RIP5(B, C, D, E, A, WR04, SR04, KR0); + RIP5(A, B, C, D, E, WR05, SR05, KR0); + RIP5(E, A, B, C, D, WR06, SR06, KR0); + RIP5(D, E, A, B, C, WR07, SR07, KR0); + RIP5(C, D, E, A, B, WR08, SR08, KR0); + RIP5(B, C, D, E, A, WR09, SR09, KR0); + RIP5(A, B, C, D, E, WR10, SR10, KR0); + RIP5(E, A, B, C, D, WR11, SR11, KR0); + RIP5(D, E, A, B, C, WR12, SR12, KR0); + RIP5(C, D, E, A, B, WR13, SR13, KR0); + RIP5(B, C, D, E, A, WR14, SR14, KR0); + RIP5(A, B, C, D, E, WR15, SR15, KR0); + + RIP4(E, A, B, C, D, WR16, SR16, KR1); + RIP4(D, E, A, B, C, WR17, SR17, KR1); + RIP4(C, D, E, A, B, WR18, SR18, KR1); + RIP4(B, C, D, E, A, WR19, SR19, KR1); + RIP4(A, B, C, D, E, WR20, SR20, KR1); + RIP4(E, A, B, C, D, WR21, SR21, KR1); + RIP4(D, E, A, B, C, WR22, SR22, KR1); + RIP4(C, D, E, A, B, WR23, SR23, KR1); + RIP4(B, C, D, E, A, WR24, SR24, KR1); + RIP4(A, B, C, D, E, WR25, SR25, KR1); + RIP4(E, A, B, C, D, WR26, SR26, KR1); + RIP4(D, E, A, B, C, WR27, SR27, KR1); + RIP4(C, D, E, A, B, WR28, SR28, KR1); + RIP4(B, C, D, E, A, WR29, SR29, KR1); + RIP4(A, B, C, D, E, WR30, SR30, KR1); + RIP4(E, A, B, C, D, WR31, SR31, KR1); + + RIP3(D, E, A, B, C, WR32, SR32, KR2); + RIP3(C, D, E, A, B, WR33, SR33, KR2); + RIP3(B, C, D, E, A, WR34, SR34, KR2); + RIP3(A, B, C, D, E, WR35, SR35, KR2); + RIP3(E, A, B, C, D, WR36, SR36, KR2); + RIP3(D, E, A, B, C, WR37, SR37, KR2); + RIP3(C, D, E, A, B, WR38, SR38, KR2); + RIP3(B, C, D, E, A, WR39, SR39, KR2); + RIP3(A, B, C, D, E, WR40, SR40, KR2); + RIP3(E, A, B, C, D, WR41, SR41, KR2); + RIP3(D, E, A, B, C, WR42, SR42, KR2); + RIP3(C, D, E, A, B, WR43, SR43, KR2); + RIP3(B, C, D, E, A, WR44, SR44, KR2); + RIP3(A, B, C, D, E, WR45, SR45, KR2); + RIP3(E, A, B, C, D, WR46, SR46, KR2); + RIP3(D, E, A, B, C, WR47, SR47, KR2); + + RIP2(C, D, E, A, B, WR48, SR48, KR3); + RIP2(B, C, D, E, A, WR49, SR49, KR3); + RIP2(A, B, C, D, E, WR50, SR50, KR3); + RIP2(E, A, B, C, D, WR51, SR51, KR3); + RIP2(D, E, A, B, C, WR52, SR52, KR3); + RIP2(C, D, E, A, B, WR53, SR53, KR3); + RIP2(B, C, D, E, A, WR54, SR54, KR3); + RIP2(A, B, C, D, E, WR55, SR55, KR3); + RIP2(E, A, B, C, D, WR56, SR56, KR3); + RIP2(D, E, A, B, C, WR57, SR57, KR3); + RIP2(C, D, E, A, B, WR58, SR58, KR3); + RIP2(B, C, D, E, A, WR59, SR59, KR3); + RIP2(A, B, C, D, E, WR60, SR60, KR3); + RIP2(E, A, B, C, D, WR61, SR61, KR3); + RIP2(D, E, A, B, C, WR62, SR62, KR3); + RIP2(C, D, E, A, B, WR63, SR63, KR3); + + RIP1(B, C, D, E, A, WR64, SR64); + RIP1(A, B, C, D, E, WR65, SR65); + RIP1(E, A, B, C, D, WR66, SR66); + RIP1(D, E, A, B, C, WR67, SR67); + RIP1(C, D, E, A, B, WR68, SR68); + RIP1(B, C, D, E, A, WR69, SR69); + RIP1(A, B, C, D, E, WR70, SR70); + RIP1(E, A, B, C, D, WR71, SR71); + RIP1(D, E, A, B, C, WR72, SR72); + RIP1(C, D, E, A, B, WR73, SR73); + RIP1(B, C, D, E, A, WR74, SR74); + RIP1(A, B, C, D, E, WR75, SR75); + RIP1(E, A, B, C, D, WR76, SR76); + RIP1(D, E, A, B, C, WR77, SR77); + RIP1(C, D, E, A, B, WR78, SR78); + RIP1(B, C, D, E, A, WR79, SR79); + + D = h[1] + c + D; + h[1] = h[2] + d + E; + h[2] = h[3] + e + A; + h[3] = h[4] + a + B; + h[4] = h[0] + b + C; + h[0] = D; + } + +#undef X +} + +uint8_t *RIPEMD160(const uint8_t *data, size_t len, unsigned char *out) { + RIPEMD160_CTX ctx; + + if (!RIPEMD160_Init(&ctx)) { + return NULL; + } + + RIPEMD160_Update(&ctx, data, len); + RIPEMD160_Final(out, &ctx); + return out; +} diff --git a/external/boringssl/decrepit/ripemd/ripemd_test.cc b/external/boringssl/decrepit/ripemd/ripemd_test.cc new file mode 100644 index 0000000000..ebcabdfb49 --- /dev/null +++ b/external/boringssl/decrepit/ripemd/ripemd_test.cc @@ -0,0 +1,119 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include + +#include "../../crypto/test/test_util.h" + + +struct RIPEMDTestCase { + const char *input; + uint8_t expected[RIPEMD160_DIGEST_LENGTH]; +}; + +static const RIPEMDTestCase kRIPEMDTestCases[] = { + {"", {0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31}}, + {"a", {0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe}}, + {"abc", {0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc}}, + {"message digest", + {0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36}}, + {"abcdefghijklmnopqrstuvwxyz", + {0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc}}, + {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + {0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b}}, + {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89}}, + {"1234567890123456789012345678901234567890123456789012345678901234567890123" + "4567890", + {0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb}}, +}; + +int main(void) { + unsigned test_num = 0; + int ok = 1; + + for (const auto &test : kRIPEMDTestCases) { + test_num++; + + const size_t input_len = strlen(test.input); + + for (size_t stride = 0; stride <= input_len; stride++) { + uint8_t digest[RIPEMD160_DIGEST_LENGTH]; + + if (stride == 0) { + RIPEMD160(reinterpret_cast(test.input), input_len, + digest); + } else { + RIPEMD160_CTX ctx; + RIPEMD160_Init(&ctx); + + for (size_t done = 0; done < input_len;) { + const size_t remaining = input_len - done; + size_t todo = stride; + if (todo > remaining) { + todo = remaining; + } + + RIPEMD160_Update(&ctx, &test.input[done], todo); + done += todo; + } + + RIPEMD160_Final(digest, &ctx); + } + + if (memcmp(digest, test.expected, sizeof(digest)) != 0) { + fprintf(stderr, "#%u: bad result with stride %u: ", test_num, + static_cast(stride)); + hexdump(stderr, "", digest, sizeof(digest)); + ok = 0; + } + } + } + + static const size_t kLargeBufSize = 1000000; + std::unique_ptr buf(new uint8_t[kLargeBufSize]); + memset(buf.get(), 'a', kLargeBufSize); + uint8_t digest[RIPEMD160_DIGEST_LENGTH]; + RIPEMD160(buf.get(), kLargeBufSize, digest); + + static const uint8_t kMillionADigest[RIPEMD160_DIGEST_LENGTH] = { + 0x52, 0x78, 0x32, 0x43, 0xc1, 0x69, 0x7b, 0xdb, 0xe1, 0x6d, + 0x37, 0xf9, 0x7f, 0x68, 0xf0, 0x83, 0x25, 0xdc, 0x15, 0x28}; + + if (memcmp(digest, kMillionADigest, sizeof(digest)) != 0) { + fprintf(stderr, "Digest incorrect for “million a's†test: "); + hexdump(stderr, "", digest, sizeof(digest)); + ok = 0; + } + + if (!ok) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/decrepit/rsa/CMakeLists.txt b/external/boringssl/decrepit/rsa/CMakeLists.txt new file mode 100644 index 0000000000..66d836b13f --- /dev/null +++ b/external/boringssl/decrepit/rsa/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + rsa_decrepit + + OBJECT + + rsa_decrepit.c +) diff --git a/external/boringssl/decrepit/rsa/rsa_decrepit.c b/external/boringssl/decrepit/rsa/rsa_decrepit.c new file mode 100644 index 0000000000..0d7c5f66b2 --- /dev/null +++ b/external/boringssl/decrepit/rsa/rsa_decrepit.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 + +#include + +#include + + +RSA *RSA_generate_key(int bits, unsigned long e_value, void *callback, + void *cb_arg) { + assert(callback == NULL); + assert(cb_arg == NULL); + + RSA *rsa = RSA_new(); + BIGNUM *e = BN_new(); + + if (rsa == NULL || + e == NULL || + !BN_set_word(e, e_value) || + !RSA_generate_key_ex(rsa, bits, e, NULL)) { + goto err; + } + + BN_free(e); + return rsa; + +err: + BN_free(e); + RSA_free(rsa); + return NULL; +} + +int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM, const uint8_t *mHash, + const EVP_MD *Hash, int sLen) { + return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen); +} + +int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, const EVP_MD *Hash, + const uint8_t *EM, int sLen) { + return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen); +} + +int RSA_padding_add_PKCS1_OAEP(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned param_len) { + return RSA_padding_add_PKCS1_OAEP_mgf1(to, to_len, from, from_len, param, + param_len, NULL, NULL); +} diff --git a/external/boringssl/decrepit/ssl/CMakeLists.txt b/external/boringssl/decrepit/ssl/CMakeLists.txt new file mode 100644 index 0000000000..fba0234d3a --- /dev/null +++ b/external/boringssl/decrepit/ssl/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + ssl_decrepit + + OBJECT + + ssl_decrepit.c +) diff --git a/external/boringssl/decrepit/ssl/ssl_decrepit.c b/external/boringssl/decrepit/ssl/ssl_decrepit.c new file mode 100644 index 0000000000..e25cbf3119 --- /dev/null +++ b/external/boringssl/decrepit/ssl/ssl_decrepit.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.] + */ +/* ==================================================================== + * 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 + +#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_PNACL) + +#include +#include +#include +#include + +#include +#include + + +typedef struct { + DIR *dir; + struct dirent dirent; +} OPENSSL_DIR_CTX; + +static 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; +} + +static 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; +} + + +/* 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; + + /* 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_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, 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); + } + return ret; +} + +#endif /* !WINDOWS && !PNACL */ diff --git a/external/boringssl/decrepit/x509/CMakeLists.txt b/external/boringssl/decrepit/x509/CMakeLists.txt new file mode 100644 index 0000000000..930912d19a --- /dev/null +++ b/external/boringssl/decrepit/x509/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + x509_decrepit + + OBJECT + + x509_decrepit.c +) diff --git a/external/boringssl/decrepit/x509/x509_decrepit.c b/external/boringssl/decrepit/x509/x509_decrepit.c new file mode 100644 index 0000000000..5714b40a0a --- /dev/null +++ b/external/boringssl/decrepit/x509/x509_decrepit.c @@ -0,0 +1,42 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + + +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, + X509V3_CTX *ctx, int ext_nid, char *value) { + CONF *nconf = NULL; + LHASH_OF(CONF_VALUE) *orig_data = NULL; + + if (conf != NULL) { + nconf = NCONF_new(NULL /* no method */); + if (nconf == NULL) { + return NULL; + } + + orig_data = nconf->data; + nconf->data = conf; + } + + X509_EXTENSION *ret = X509V3_EXT_nconf_nid(nconf, ctx, ext_nid, value); + + if (nconf != NULL) { + nconf->data = orig_data; + NCONF_free(nconf); + } + + return ret; +} diff --git a/external/boringssl/decrepit/xts/CMakeLists.txt b/external/boringssl/decrepit/xts/CMakeLists.txt new file mode 100644 index 0000000000..7dccde0377 --- /dev/null +++ b/external/boringssl/decrepit/xts/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + xts + + OBJECT + + xts.c +) diff --git a/external/boringssl/decrepit/xts/xts.c b/external/boringssl/decrepit/xts/xts.c new file mode 100644 index 0000000000..10a696de04 --- /dev/null +++ b/external/boringssl/decrepit/xts/xts.c @@ -0,0 +1,258 @@ +/* ==================================================================== + * Copyright (c) 2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include + +#include +#include + +#include "../crypto/modes/internal.h" + + +typedef struct xts128_context { + void *key1, *key2; + block128_f block1, block2; +} XTS128_CONTEXT; + +static size_t CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, + const uint8_t iv[16], const uint8_t *inp, + uint8_t *out, size_t len, int enc) { + union { + uint64_t u[2]; + uint32_t d[4]; + uint8_t c[16]; + } tweak, scratch; + unsigned int i; + + if (len < 16) return 0; + + memcpy(tweak.c, iv, 16); + + (*ctx->block2)(tweak.c, tweak.c, ctx->key2); + + if (!enc && (len % 16)) len -= 16; + + while (len >= 16) { +#if STRICT_ALIGNMENT + memcpy(scratch.c, inp, 16); + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; +#else + scratch.u[0] = ((uint64_t *)inp)[0] ^ tweak.u[0]; + scratch.u[1] = ((uint64_t *)inp)[1] ^ tweak.u[1]; +#endif + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); +#if STRICT_ALIGNMENT + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out, scratch.c, 16); +#else + ((uint64_t *)out)[0] = scratch.u[0] ^= tweak.u[0]; + ((uint64_t *)out)[1] = scratch.u[1] ^= tweak.u[1]; +#endif + inp += 16; + out += 16; + len -= 16; + + if (len == 0) return 1; + + unsigned int carry, res; + + res = 0x87 & (((int)tweak.d[3]) >> 31); + carry = (unsigned int)(tweak.u[0] >> 63); + tweak.u[0] = (tweak.u[0] << 1) ^ res; + tweak.u[1] = (tweak.u[1] << 1) | carry; + } + if (enc) { + for (i = 0; i < len; ++i) { + uint8_t c = inp[i]; + out[i] = scratch.c[i]; + scratch.c[i] = c; + } + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out - 16, scratch.c, 16); + } else { + union { + uint64_t u[2]; + uint8_t c[16]; + } tweak1; + + unsigned int carry, res; + + res = 0x87 & (((int)tweak.d[3]) >> 31); + carry = (unsigned int)(tweak.u[0] >> 63); + tweak1.u[0] = (tweak.u[0] << 1) ^ res; + tweak1.u[1] = (tweak.u[1] << 1) | carry; +#if STRICT_ALIGNMENT + memcpy(scratch.c, inp, 16); + scratch.u[0] ^= tweak1.u[0]; + scratch.u[1] ^= tweak1.u[1]; +#else + scratch.u[0] = ((uint64_t *)inp)[0] ^ tweak1.u[0]; + scratch.u[1] = ((uint64_t *)inp)[1] ^ tweak1.u[1]; +#endif + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); + scratch.u[0] ^= tweak1.u[0]; + scratch.u[1] ^= tweak1.u[1]; + + for (i = 0; i < len; ++i) { + uint8_t c = inp[16 + i]; + out[16 + i] = scratch.c[i]; + scratch.c[i] = c; + } + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); +#if STRICT_ALIGNMENT + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out, scratch.c, 16); +#else + ((uint64_t *)out)[0] = scratch.u[0] ^ tweak.u[0]; + ((uint64_t *)out)[1] = scratch.u[1] ^ tweak.u[1]; +#endif + } + + return 1; +} + +typedef struct { + union { + double align; + AES_KEY ks; + } ks1, ks2; /* AES key schedules to use */ + XTS128_CONTEXT xts; +} EVP_AES_XTS_CTX; + +static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + EVP_AES_XTS_CTX *xctx = ctx->cipher_data; + if (!iv && !key) { + return 1; + } + + if (key) { + /* key_len is two AES keys */ + if (enc) { + AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) AES_encrypt; + } else { + AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) AES_decrypt; + } + + AES_set_encrypt_key(key + ctx->key_len / 2, + ctx->key_len * 4, &xctx->ks2.ks); + xctx->xts.block2 = (block128_f) AES_encrypt; + xctx->xts.key1 = &xctx->ks1; + } + + if (iv) { + xctx->xts.key2 = &xctx->ks2; + memcpy(ctx->iv, iv, 16); + } + + return 1; +} + +static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t len) { + EVP_AES_XTS_CTX *xctx = ctx->cipher_data; + if (!xctx->xts.key1 || + !xctx->xts.key2 || + !out || + !in || + len < AES_BLOCK_SIZE || + !CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len, ctx->encrypt)) { + return 0; + } + return 1; +} + +static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { + EVP_AES_XTS_CTX *xctx = c->cipher_data; + if (type == EVP_CTRL_COPY) { + EVP_CIPHER_CTX *out = ptr; + EVP_AES_XTS_CTX *xctx_out = out->cipher_data; + if (xctx->xts.key1) { + if (xctx->xts.key1 != &xctx->ks1) { + return 0; + } + xctx_out->xts.key1 = &xctx_out->ks1; + } + if (xctx->xts.key2) { + if (xctx->xts.key2 != &xctx->ks2) { + return 0; + } + xctx_out->xts.key2 = &xctx_out->ks2; + } + return 1; + } else if (type != EVP_CTRL_INIT) { + return -1; + } + /* key1 and key2 are used as an indicator both key and IV are set */ + xctx->xts.key1 = NULL; + xctx->xts.key2 = NULL; + return 1; +} + +static const EVP_CIPHER aes_256_xts = { + NID_aes_256_xts, 1 /* block_size */, 64 /* key_size (2 AES keys) */, + 16 /* iv_len */, sizeof(EVP_AES_XTS_CTX), + EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT | + EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY, + NULL /* app_data */, aes_xts_init_key, aes_xts_cipher, + NULL /* cleanup */, aes_xts_ctrl}; + +const EVP_CIPHER *EVP_aes_256_xts(void) { return &aes_256_xts; } diff --git a/external/boringssl/fuzz/CMakeLists.txt b/external/boringssl/fuzz/CMakeLists.txt new file mode 100644 index 0000000000..5bef3ae97e --- /dev/null +++ b/external/boringssl/fuzz/CMakeLists.txt @@ -0,0 +1,66 @@ +include_directories(../include) + +add_executable( + privkey + + privkey.cc +) + +target_link_libraries(privkey Fuzzer) +target_link_libraries(privkey crypto) + +add_executable( + cert + + cert.cc +) + +target_link_libraries(cert Fuzzer) +target_link_libraries(cert crypto) + +add_executable( + spki + + spki.cc +) + +target_link_libraries(spki Fuzzer) +target_link_libraries(spki crypto) + +add_executable( + pkcs8 + + pkcs8.cc +) + +target_link_libraries(pkcs8 Fuzzer) +target_link_libraries(pkcs8 crypto) + +add_executable( + server + + server.cc +) + +target_link_libraries(server Fuzzer) +target_link_libraries(server crypto) +target_link_libraries(server ssl) + +add_executable( + client + + client.cc +) + +target_link_libraries(client Fuzzer) +target_link_libraries(client crypto) +target_link_libraries(client ssl) + +add_executable( + read_pem + + read_pem.cc +) + +target_link_libraries(read_pem Fuzzer) +target_link_libraries(read_pem crypto) diff --git a/external/boringssl/fuzz/cert.cc b/external/boringssl/fuzz/cert.cc new file mode 100644 index 0000000000..b8815a5a0b --- /dev/null +++ b/external/boringssl/fuzz/cert.cc @@ -0,0 +1,32 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + const uint8_t *bufp = buf; + X509 *x509 = d2i_X509(NULL, &bufp, len); + if (x509 != NULL) { + /* Extract the public key. */ + EVP_PKEY_free(X509_get_pubkey(x509)); + + /* Reserialize the structure. */ + uint8_t *der = NULL; + i2d_X509(x509, &der); + OPENSSL_free(der); + } + X509_free(x509); + return 0; +} diff --git a/external/boringssl/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be b/external/boringssl/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be new file mode 100644 index 0000000000000000000000000000000000000000..25e3980ac951306fca8f88df68cb49d630bcac04 GIT binary patch literal 1080 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|6^CdO=oCdPCFS)kPo1`SLaZw*))1e%yL z7BGv5G#E}2Hb4$|SydL0mpHW97+G1_nHibDtYz%XOa?kY17rnNfPrh!V8Fq^V9RHyC8VEMR10i7|*W(1!61nA+qsN=gc>^z{p} zGm-S`yL&pi8|ft%l^`i*gey+Y$xO{FDK#0QR*kABz}^$YHZ*U6XSd^|a#y zqy4Tg5KIqPebs;m zwQ<|-B&l6djrs~5l8KekfP;-Ky^#l)jtvYzO5|BI4b%-( z7bq`KggY6B|8me0Jady3BO@q88B#6I&0FZVJThT{BQT4A@`z!^w;Cp3o>865{}iNc zzt6^hJ71{>?0SA*^5I{gpK5`U&mb9!S!nk&B%{g9U_Pk|In>Hvz<3AeFktcnh7oFh UhGa4<#Q`wiStIh@1z^4d0O0)^F#rGn literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f b/external/boringssl/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f new file mode 100644 index 0000000000000000000000000000000000000000..ed974654d1b64255bfec3e699e91f4da51050d21 GIT binary patch literal 1022 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%SHfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhll%xo;GVzQw?2Xkn% zF|x9DJihh*DuJ<1naL!1^HLs-P6(CNH4jl1W7R?Tyb(vW@=tZu_2O; z`uWMl1qQMpNAj_Vv4|Wtd)75Mhfz;EJ}}zv`U1i9fYnzGctFy^jEw(Tm<$*UBEf)psQNEt`~b#ehif`#!~B@-*70S6nK zReB>2Fc}&cfYivdXd0*+s4h@mpa^#(%tJY-9?C&Wugp!1j0~w3=jJW+TOOI`~ zSLy+~p5K>zxc~c{od#`x<@0nI+4O@l51llAtNMoDV7Xf9{JV#1S%*;~=%SRk)7FzfkpDpmL~CZe`AB_A1~!j*ZEzI@(blF_&Kj0@=OXAl3XVEX+*o4F(x7V;C7(Vho}b zv|)S$rZ)MEl9B=|ef@&$OeFpK?w*eBMtaFbB?bt^jBv%tIhm<>CB=rwI`Wf?3m|^r zV-aH!Ic)Z#8YMg26}^t*IhO- z={?^vs>;4LZrhzCwJWMo-#`(hK!HWdKmw?f3m7IWjMpleSQ!mC*x1q=d4Q?VzyPE~ zo<-9@-9UAL@&ZM;6ALo2`X>i1xiU8~GBTuEoSV1MZ+T>b&&Gc{U#SP|dVXK>;a~YY zT}C$jpv*%jjo+%i;Wt>WRyzOg;VcuuAisZk|3637O1ItLw7X5^Wal)AE24tMCIv;e z4>EfxY|WBubWm6%x$uBNgF(Xr28IR$gN_pn1~M!S`@e5!VrejFV$PVe6OxTIISezb zztyNt=GSU!SZlz`%$8wr!@5%TR>XnJ4mbaFy>Rn-FT8a9Rm0kf3o|rpl5gsK_}cwK z<(c5YMF-+viWv%iT`)~PvwLZav&grNwR(zEPv*tW+_Qplx$m|PtE=wocx&SyYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fYBDgZH!<=v042DXniv@wZk>@xHu(ERTv;lt zF8aPrj>VJ0?G+QR>{)oj=f?`?ZSF6971=pDZbj&)S!(WOt>~U>@q%@GR$bweXGap2 zZFt}Cq*H@`p6a!?&7apUn|OT2Nhb+Yk-2MUxJ}aYKlQQQ`JmX;aNU6Sow^NG;cGv= zi_gBq(7RLQhlr@@%>!hTc2z z=2DzR@Y5Lo9^HQd%4UDko}KPnVkyb6eJYdXL~g!+7J3(DS!aFowae#cmtC(T*Pmed z=$Bcru;rCFHSOEBD@67hy_R6s2x2LGy4u+Gp~Y@?vzDYem9NAMzQiBUeo>hH{qmWW{D+1yUf- zVr*b&pua$Ofp(i_MoCG5mA-y*QI1}EYJLeQTJ@6ib3p>d`o-YnlbomreAjFdV9rM{{M#$C;YBCTWr{AP%CjEw0Tk1X*0n& zFFeu~=hp8KzT*C`J1V9an9Wot^FIYywEz2@ozFD1Gz}~m{;azxZ6s;2db)|os%e*A zFP0JE@Z7fh>BRTVX0K(#@=x8`Q=B~ENqx1Q(rH`vxA7Jwa~?AX_$^#N<6Yt>0QW;w Av;Y7A literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/04ed1e2c50886acd723b3a78d4bafd49938bd14d b/external/boringssl/fuzz/cert_corpus/04ed1e2c50886acd723b3a78d4bafd49938bd14d new file mode 100644 index 0000000000..2765f008a7 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/04ed1e2c50886acd723b3a78d4bafd49938bd14d @@ -0,0 +1 @@ +0†:;€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41 b/external/boringssl/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41 new file mode 100644 index 0000000000000000000000000000000000000000..2e7495721b34ae0d65e5ba7c52c4cb7f51b72045 GIT binary patch literal 778 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 zk~Zn7{nGq#8V8gFJ`Xk=yp22nVi&cVawoS2iDmS2>YnP@0xAOdvy z1$G`@-~7@)8~5+uw;(JtwH)qG9xiue4}<*%^e_u^D4T&Y(8F)AdN>>8VG|?|Q|dq# zhy(LV5;OA@&>aYKLb9QRffzUA*@=Ng^3Ikf@pOMK;J=AbpX&Ote~U~ E0Q3XOX8-^I literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0694a2168fe7699e2dcabe3386a80bd4209094fc b/external/boringssl/fuzz/cert_corpus/0694a2168fe7699e2dcabe3386a80bd4209094fc new file mode 100644 index 0000000000000000000000000000000000000000..2f9e77f7b96ab38a887d8558ab795f72fba5818d GIT binary patch literal 12 TcmXqLFyLTdFlaDnU}^vW5Lg1s literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3 b/external/boringssl/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3 new file mode 100644 index 0000000000000000000000000000000000000000..bce3ec11535e7a97042eca0f16bd9d079473e4b2 GIT binary patch literal 1934 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?l=1mRXWb8zt_=47Vj7v*Ip8j2Z+ zfUIKY;q}cg%_~XF%u@)LHEluL-{>BE;KVHh6uJgMZ)B z&Bn;e%FYb53d&+K&;dycvH*jw3Eg!~0-1S9`4!0S#c*-omKyMK7 zy2~aez2{rT*0QgS+jb{O?TTvDH&6sAP+*ZVkO1oB0)_+&ru9cE3=0 zCU|hsf%unVhJs%gOq0*-UfSX;@@-?S0nPJTNl9s{qXKeXGa)9gIiO~14jwLN^t`5t zH?P6V0NUg=wE@d(Dp>QH0!4W(RX;g12ben%c}-7o>dCy=nR`|+F8AHmVRhAg9dE5m zoF%uIP$|#!|2)3B;qzG8js)987nt;2$g}@6r*+rAi6XxFd)xvhRi{49Tp;v*{&XMV z#+j1erR#V!;*|0P7A0?o}k_{yc#K7+2;m=LX%+X5+yI3zdKi44A zK$wjk=*@GsOpNRtUUSYN!hPks?Wb!#AVc`r2i)N^4{u<#Z8Ra22G6V2C_h_WmQ=~ z4(8BiV`ODzXJ%yM(0c=6G8yQA^$Rkyq5AWZ^Ox$odpf!s=@peAsbz$#P0qV=Ai&7Q-rxulDre!84mZSpH$J7#5ND2WZ4+A3uQzJtI6HtNxB@YV&3pm%n z3B^VuXiDG`=5;z{B5iiubDEWF|KV}>M4pBJ|TNHTSYsbkDVT!MZ)Gu5ih-BMHkk zyl;5Yslh)__1fF!&uf=WJU-*3lZ2_r+_f{@Q1aR&J^xc5+no=JO%2x#c;BhpP!+!R K(>t5&OAG*{!!C{h literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/094d3581e71a4316a567e43e6ebfa63b95196b8e b/external/boringssl/fuzz/cert_corpus/094d3581e71a4316a567e43e6ebfa63b95196b8e new file mode 100644 index 0000000000000000000000000000000000000000..8d21c6f48954b06d268c1adb2d4dba4f235bc648 GIT binary patch literal 1384 zcmZuxdrVtp6z_fXL3tE*D-X3$$3U>7J-66e&@DoSRJIU_ZnMI&ObL+~BQ6ucS2h@%im=UToDbG)88~$df{)>MJJ!|2`_KKp-~H}6 zzjJ=S^Fe?(2Lb$}Ac12zE^`f$>k>AOR6)EX=ApJVZGXgLSgcqCC3GyrNC+D#p>SIT zO+k{dkyCOD$JMzRb&1D8XF;X_64d<>kY{`zhF2Fg@=ngj^4rxv=pj8No;J{+H_;}8 zG2c{)wnm`!MhHKZ!2WM4S)AN#ceAye&%@g3WKasJq;c`3T%(7#vmW(&mU%Y9D=wN> zDkO(_r7O1CS+}+>%vkH-w!ucAAXg$qg`Qo3V-i_-L10p%SVX3M_g)~St}Gv_=B}on zZnaKUT5SpS^N05iiJF&vu6m?@ZT91xH)fA_zi#^3U*o#AyZMXhZn?f~sc!n|uLql* zJps%G0jv&GD7h+&6e!Cy5=<`b;1SFPPwuq=J7)PUzQJWbb&(^XII}d*F<2f_X zP5MznXOK`T{q%kccLs})Ap}R1J7=H65fSFDih_io2ZNr5hXv6D2~A*%Y@s;9EbNv= zwd7R1h2fs`H8${qU$pdnkS6dWs3j5H;^u1XZne1xwQgy2!I)S?1TcjN;c`5HVWNv; zsSfz(W=iJ0>szZXJ?1t|c?X(0CO&-g!rHlG=J$!Kr4LAD&tH5>S6h%fC~kW3km-te z;F(tMk$7uXvfK}k>XT?@=#yb>iycX(cku%KThu4kXL@a zJmL*MVeRJ+DS`;IH;l=m3E8D8Df>^s#lG-A`7`SR732eY@1T{^of%{yuhO-wew zm3GGV{i*5k&8CXWo67d)-73#C{#_e_2N!ZaAt7+5&!=BHQjjJZ=)?;;ViRtev|p*j zug#XOpT-KRU}AH&=Gzs=l!N+fsYK2br1x@f{)!(>C#1&RH3zpF zlHq3cu;z-_H8qbDmh0-tjJmk(;0rS!~hE zfVX8hdA`0-r>l3dQUB{KB}Ep!*5Tvt9&TYi7#*{MLWoRZ*a9gA0=>c(Rw)DkWy2&; zhz&HEp?zyc|9)ntz7l1rG{0 zfX?A_H|QF|Q{k{9if*t9l+>gJR)JYU+BDVcs;uXONp6xN;=XTEQ0|S#&72g?OG9aXTiGUVf2RRJYK{G&h?B!W7 zVu#ggUE#1lC~z$yA8&;+9HjL34-U(bWX$vf*C zYMma%Z2;cU04tvd#0(Uhfuc2fZL>Ehc84P&(d#gS2_vcXhPH4tBzeUU_qZrLpQbfS zYxP;QU_F@AwDJyl#h}fYa#l_ z?UK)5aL;<&9l5=Ko_=+T7%cy+_<;|0ZE8GzcQHBkhV#c*SI@792fvsf(>mfC?eqJu zemod>OGZ5)BR>=?(8X376V_BSNTotdHKS2eilwGV*n-nWTKRKwnq7B>ot!U*y2Ab0 ze08`wkESV79fQE?g=&Q8r@#ZswJQK>AmgP0N$TBdxA*plS?BGpmL`|O=8H&K#VAwk z3yMNW>f^IdgnfOz=^k=vGi|!ukUDZKh-}pdcJFh4oiO^_-<<_LX2l}3Op`!BDfY@} z<)^=BYQ4^wi!Lq(&Of&>a$&M-!-NM$EOuPL(HoSx=ozg-nMQL1qzZwCVf-U{%0y?riK*}q|zdw3MNz8H>y+w?_T>T^C4H^NNZX3_@?Na*DoKe zGwyNU3oYOE3>U?3d^i~|pLylP`mgRY_SJpY8@WWaa_0}0j5Km%g=eO}*)~x8?UU12 z8?XI!Wm^Na2J9T0j@yNv!NXq#`Kz2Yu&#UjP6A literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5 b/external/boringssl/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5 new file mode 100644 index 0000000000000000000000000000000000000000..902db253103fb9909d1e723074ea1796114a3a4a GIT binary patch literal 1217 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQWbe~j(oV;X1RRd*^AhWOxNH8Z=!85NUwJ0yOM8UDNBqP5l zv!qhN-N-;roY&CQ(7?#T(8AQr*dhwZH8U_YGBW^!D1%I_R&nrfIVa|1rsWsqWhNSm z8HfO_y1>rE>ziNtbL0N~`xL_ZQp@4);sLu0?1W@P2?H^(yLk9>6Ek!4(!q|?OU}z3;CZx(SGwJGVpiM_nHI%9DYW41vPW4eJX&}vy# z7LbEEwAmP0S=pI^RzX=z1|V5M7GTIVfgNX!a9oo>W?oW$1+sIwL8|##SeTjE8w@gF zrZ6(H#2BbY8EC@<44B&FGfGMdtn~E@vNMqk(0BKAbT`sVE-FD%%m`PUoRgWFS5j;U z)v?Z?!JvUj;Qt(v4Q(3M4Z!fy&rdEcfcU77MT|w{u-UV&$vKRA+VO$We%BWWrU$IP zYQO_>q%b4ne-UGYpUpsZf${=HxEFDRM-C#nbAr=5a}y&YL#oBO zc?%H*O^;ZpRD=y5?tVzD9^Wkgv3zcVr2NxZPw|XgN zDEM{3H2KW#r7g}P-!|6jDNa3^7dvy$3dZHW+d8bSy07D{b&0d&76UqhgMk6;lm?+v zp6UO2e09U;v9cWrwuzpzQ&U5$z@+a&p8cmet-JnB6!Fd9;})Q4V8<}2I`wJh0-^Ww zrvpP27@Ah#Fk%3v34;b8*~DB64CQAKPcaMaeufA_MqnyuFz`do#sUU>z=#Hx80@Zv zrI~4o6^6RNL3vN)Ax5VPIrnYGi0& P0xBp##fF7}g^?iu#wc#; literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0b2f2af22568510301982a60fba3763b6ca92409 b/external/boringssl/fuzz/cert_corpus/0b2f2af22568510301982a60fba3763b6ca92409 new file mode 100644 index 0000000000000000000000000000000000000000..d48401c68eae254289668f132fa3281e11a98a51 GIT binary patch literal 12 TcmXqLFlb<6`p?jyX3zit7nTFM literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e b/external/boringssl/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e new file mode 100644 index 0000000000000000000000000000000000000000..220384f71bfabe6e107b92105c47cb8186ae8166 GIT binary patch literal 1959 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O`B4Xc8#|hO)MY@xIsXpLV#NKEdZJUG$MOHOCVq5$!G&!uqq9( zbplA%0o7jvsb}NVYV&CO&dbQi&B|clX~1p3$;KSY!Y0fV8f++RAjrnNAQZz)G);!6 znhb%OLRq+kx!m*f(|uAEa`KW5RSlFug3Q7)AiPvc!8aV*EhfP&&K`x_bmv^Of83a2Iwvxu)DxcNH&x(5Cgl5hd&nc?=Qv;BcTxl7tjsl*Ayk5THTfv;kUpV$ZHDkisdiBr!7&E#R;h zPC1F0IeO{fl2b1^Ki44AK$wjkSa6@SWnyIG05h~0*_oXfSS0UkX%bKOH#Ug=@lx(| zo!`|czfit{pYwY5GgPY_l{MesqvkO6^S7OgW?MXNNXmZQQhol-A}*sgCH*(Cm-kj@ zEN)`VHfUl@H;@IEi?XULpwg5>n@xz3m6e?tXqPq{n8jqE1CkeH0ft=@e=e%?nglZQ zlJYB%9n1|<&CkNZ%*5VckO4D>k&z|FAj-->8zR7Nz|1S%*;~=%SHfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*M#o6CV|Ynr2GnG_i}?&^RuupGqE=qWWbDJWMqjkh%(TI z@eP>TfAn33^63zGqZfjr2G$}GSzZxHdi%O)nh z=Uc|svagNXb|*>gifYt1Py{JZV39JA0BYm{1_TS^wMr&dMgtBuHmmeT9$+doFaW8M zXVElJH&9)myg(7|L>&IfK})X8O^l2TsTSwvE%aL+nc%bW-_BR+0lS{xmwdSY`<$Hy zZGYwSbQ#(7gE9}DG=8i4hTmYhTIu||hqFusgZ%#G88jF)FloFsXkuv)XkyM-z$_xt zU^q$GfC@RqCsiSb>N(~A=crogw)>lQx2c@$oF;KaRIu2jpy>8NNN)8~*qSBR=%BDj Va^Zm+)|Im0+USYN!hPks?Wb!#AVc`r2i)N^4{u<#Z8Ra22G6V2C_h_WmQ=~4(8Bi zV`ODzXJ&-6m<)74(t<3&pld>RU6Vj&UQ&JqvU|Bfs`*)1n3>oc3^HKGFfy{l7(^*( z!}tbFZSolWbR zBE}+e*z8%?%H*O^;ZpRD=y5?tVzD9^Wkgv z3zcVr2NxZPe<@}t_;tZF`ONO6EzTm}HrDDXPCc0yJ9Ezp#^t`-I;^g`uj8$CiL>Mu z6DsAI{-4KJH+&u|+mT?K=mL|z3widR=CtnmH&Mhle~(+hB+ly8rK>I)qk literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0c30def9baf58c5be015cede0594b4bd73507f00 b/external/boringssl/fuzz/cert_corpus/0c30def9baf58c5be015cede0594b4bd73507f00 new file mode 100644 index 0000000000000000000000000000000000000000..67f9146b32d8b60070578cb5f51d9795bb623dcd GIT binary patch literal 64 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5MuRk}y-o0!L;hMn)zkj)07BHB1IgOsbRlpBnJ8 Uaqj;V{$l zA|R{Sd3b&EOY=$+GxHR}GE>W8in(|Y?n*Y4Fc1T~i-$iqF*8Rm9qeMgP$^1|825~UlD@Z|{3=d*qJVESkh!n);rUphv7(twY9K>*|AVHj&1`6Ut zyg{rCjCzzH7B>)u1TkNEc{wbEpSJ^pxQS5-*`tiC49rc8{0u;GE~X|%Mush39W!-G z7_+W;iFa*NGI_Xt;-O@v3}O2(hT&%?-Z;5s>z8uLD#i4UFPrVors%7m+W%dFN1FMz zx}DptCjNhoj;#*s_WbKzv2@v_kO_}2mK>8?dd|+spJiwI#Yd5grE70yh;I5YVaZYh zF}wJzo9rSN+gRsVJSa|ma>Z-P=E+Ytu_=pO`TYF6>2}vQFWK)t*mF8sxx-4Xua4>0 z_GZ2QSutM&1U`MRoqct^rsQVJdc(}qdzPDpv@bZI6?%DMxZU*T8IRqqQoCOm&2T<@ zaAWuKP`P5hM*S_Za~>W%zg#bWgF!-U;&P_#d$M2h?qH}mHUC#Zulz^tB_EbC6@5`Q zeNZ7IY0JdS$iN6pFy6o*afc)rRTfbC=FnziWMyS%2Bu6Xi^-tDpn*x_Eh0gQh%^{Z z5@yO+;0VmVp!^F;Tuiw2>wwauAPX?3Hlbt&VDhX5mIBWfu!BkgW})5BkRweASOECJ zlgx3Z&|pIW13plMa|yG%7DgIq@~i*XIK+Z*7ZW2h*e&zd&H<%$E1+qf(BdRB4eSdY ZbYCP^80s2mgAC;sR&gyXh4?Bn4FKiYWD5WQ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0db3ab78e42c2aecbc7b898501c4f91ba91c200f b/external/boringssl/fuzz/cert_corpus/0db3ab78e42c2aecbc7b898501c4f91ba91c200f new file mode 100644 index 0000000000000000000000000000000000000000..24f68d985fb120ec72c6d9afabed49de2382981d GIT binary patch literal 64 zcmXqLFlb=Xcx%w)(qM3iIb#8{h)9FsBw?nE1&+*`jEqc7903{MG?)yUm{ce8KQ-WI U`NXBVIhfHf~@LMw^wI;`c8w?OihoB7Gy>kfmpM9U-zWaNg=l4Fp z7g($pSoEuA3`I~>Ty_?JIeOiN^$;bT^;}?O;IAkIiP$NCd@=%N39({a2xxH;DT7!( zkVzy4hOs(mRld_qra&?eVv%zhYab7JX}6R1s`7kZ8{@Wnx2X(TNQ#dlvq;cVB$cJh zq)NC@2c%X9p{E4wQ;B3#iEweGL~nA~EsWb~H)$0h=ktgnqY4hjWp7P7P?Eat`JrKNzH3SrsId{1SR$f681^QznD@$#pb zLC%51kYcj9Dcs;-N=*)xJ`Y%A{`5AG*#eA3qyi3?pe%yK+_{`!hJPQ$CqJ{McKzKK z98{mHv#O!z%TI5u8b7K(iQO-FRwRDs&TAS=_QEqn)$W7T0MWU%)^#}e?dBsLBmTZ! zY0^U}y~Fhn+mAGKH(gkkkR?CZ-n3$0M&ZRj-qwGuXk44VdSq9+fBV|@KObx=yCK+X zl8?)0XWc%xqP05me8brb#p)~9_b)w=y5;iStM!Sli^gEj&Faq*uN41se(1(Vs;GZM z;hyx#)ycZYmf)p#4`(L|IvdgKhKT4%D&u=4@zGepQbsCL9$%F7-sbFI|JD`BvU@hB zs(;EoDnFwgOu*7!!Cn1rnYs649y(E8x+lbLs(CS>FVTU;?DIZWQWv08`_n5`L; z%l+g&8ER|J8`LsoP&UTyEM=;A%eu|9N8_d|7?0h{xVKH8K!Olpb#;O_?!`HcFDc>z zAUshgzBW4cCd!#FNpKG3D=A3Tee=( z#U2<~32@xfTK?84S&w0IcgY6NUD$g EA80$U=Kufz literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de b/external/boringssl/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de new file mode 100644 index 0000000000000000000000000000000000000000..266f737eca0a3d599649eb3401f2c9ff9085a7af GIT binary patch literal 1186 zcmcgsOH30{6rDHoIxVH;*QR{5P=xZUws%UX4aP(?red%{3?>wfmZr3mmbR9uLQqpC zrVHar;!0yG3thO;L`?vt3**9=posxD8e@z#Dz1!x3qNnhP%8nK&g$Ja@7;6Gz4ts2 znFSE(*)&5VnpTA}xTmP^aX)C;f|k_2)Up<#LInk#Tp<*&OfP12bnhWf2c=S=)~Q|5 zXdvu2bw+%g8S11>Mz=Y)Dfr_NzhLS}2*GHa7e-AkJ5-lzxi${$PR`lpXmxr>=m5^{ z0QvI(zb=$Yqu%2U^MlcNg!gg=&`VHCjrKq^5fQw6#B`YVpUUylWdCRALv*mkvX@MMyyI+Fi6Slrf}uUJ7Rg@U@P>me5ihM);;fW_ZG#zUA>T@ z#_As#x8Le&*mdd4($wT-=iB5!=+n8er;C$nduoeq@#ymhW5G!gg+N3BFcRoEBq2#R zeFhOHOGGA^X7u_bcTorVwKtlvq)KIBkwT$l5G}8+D;XNLk{rg;dQxAKNJUW~u2mwI z@R5ON4rYXi%mp|}aB`S*Q0kYgzEDbAj4?wilMq}*MhG7P4_H=Xpi?zLL5Q{6Y_SlZ zS3R4nv%_V#`r<;~VU#=U3-kVnFwEuOi28*;sDNS6k> zZ_a~8Vx?P48lj(<1`2AVzjc_jG^yYJiZyJyzZATC^6U7$nSrWl&$tb0r2{5h1r;Qd zniLbGg;838K*gpz$c#%v&IOlF(`4w)6UFa<4UB8ZCV+IY1~)?^nA3IX+MJLLREO7C zgb~{jlKM>fopV>Oxo`9xUmuV-E7NuR$JEEh?&Tm-@#Ztxn=OeIF_W216LXTOrojETx0{GzOQ48U9;?fg Xdru^I`B@qCj&R$W0ct4=%cy?=teiCa literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff b/external/boringssl/fuzz/cert_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff new file mode 100644 index 0000000000..1c8ce6f6a0 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff @@ -0,0 +1 @@ +0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad b/external/boringssl/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad new file mode 100644 index 0000000000000000000000000000000000000000..3b2ca66c0a5504958499142d0c5318765669f82e GIT binary patch literal 1027 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?l=1mRY3@NhXN=47Vj7v*Ip8j2Z+ zfUIKY;q}cg%_~XF%u@)WsxrjM)ZFjOhllK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*TkQT>bfR@%)F%h3S{?kgH-dgurM>RHyC8VjA3MCi7|*W z(1!61nA+qsN=gc>^z{p}Gm-S`yL&pi8|ft%l^`i*gebnQr=OgYnVMHpY>2EQKe@O7 z;s-t!F&2@-X3x4N=P>GN#|K9HU0)!W9D7t-+ z*-K$-mRzHQ!Xn9q2X0tb%HE1NaM|JJpRN~fUhjpMuD@znTXA8AW=--HL!UC6WlG^cgfzlkEg`Fq>~CRL|C&0HY#e*SbH;l`Pg-=*t# zG~$%<1mz7H3>ug;-WoKqG!!&3XDnbA5os`-B+Qhtz!8|EL0Q`H#kU#;0|PAiyom{% F(*et@Jb(ZI literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1 b/external/boringssl/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1 new file mode 100644 index 0000000000000000000000000000000000000000..a342e7e48c1d11f2de886fedb02435d1f56f6a36 GIT binary patch literal 1212 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&e2?c8#|hO)MY@xIsXpLV#NKEdZJUG$MOHOCVq5$!G&!HcqWJ zkGAi;jEvl@3mwSGGdQPf>XI`?Qs(~^{kXcyf z4Nwr~!Uh4bV?hoD+I5ZUcEKG`l3J9PTB6`sT9T1plvz@#;BI6fC(dhVYG`0&VQ67$ zW^54!ziMiSCW{Srx2Ez zS`H5b9^^2PFc1TW0S|v}VrGtBIyiLnlJj#7A`OJu*nvTM&X$RhjRVYJW@Kk}VqlTH zv!zKq-QU}KrlUE^;H8NkgJ5za|9#fe- zvuGNq8>lW&UZ4nfG7kUcpk*EACM!lpP>y3rwKz9#q2Kbz1aO80-)G~$ zov+jbc0Io@`S7oNo-QMseo*G2lg4jV-|!nOS1X-=_i&bpV36Oxy#Jr0YNgxmZ`$3a zaVdg12vUU=#HtDxdQ zLrc@Jw&KDJ&6?z!Iv>7vzfgH5cyQ5y_?Kdaf?pR*lh5p4+TtwoZDXyT;?$FQu`~BH ztYBR3yRF0Os{1AR3;|7lL^u748^7#T!- O^Y=i?B?dPprT_pVuxT*> literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/1108c80f8912d5d9492de40e48dbdb7e44ae4a8c b/external/boringssl/fuzz/cert_corpus/1108c80f8912d5d9492de40e48dbdb7e44ae4a8c new file mode 100644 index 0000000000000000000000000000000000000000..d30626c94e76bd105324d5db786aceeab0fd7e07 GIT binary patch literal 63 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRk}y-oE=OiXW=19^j)077HB1IgOsbRlpBr$q Taqj;yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#GL;c3eJuOO^iy&9${o zSY7men;eTLh1)A8UfHwohR=@`&fAz@`YN(>bli&2PqWnA%UaPr*Wv~1_N=luHs>0WP zdKaI4iJ^C=$PW=w)0+p}7FQRYn7IFBsP@?l)9vP{rJT8cu3571l;5)}SF2Y_o(;Ws z;?1Qvi{Pg*{yn}D-Vb1Gkn8GMO9p#7pS`^irx zW=00a#f={f8s8eo0|Qc4nMJ}ttU<)%S;kN8OPi)%cfX;mAmDF2W5WC^2C^Upd@N!t zA_uBwWb}6aUd@`qBUrntHg(6TGkymAAZcMn#{Vp=2FySToI+&zK>{qmWW{D+1yUf- zVr*b&pua$Ofp(i_MoCG5mA-y*QI1}EYJLeQTJ@6ib3p>d`o-Ynlbomr8wHdH&YUDWof#dk`!n(9~hu&VXmjD0Z!wJ7@&K4VX z8q`W$2yI@Jb=pjD&I^yU#kuu6gs-^&>yC;k{ggsTtEOFgy;w$s!*kp2 urxV{do4u9|%RhB%PjT{uC-v2KN~dkv-^N>%%z4Zl;J0x7jCYBjTI>PyokCs! literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92 b/external/boringssl/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92 new file mode 100644 index 0000000000000000000000000000000000000000..dab734038597a659604b4288226a2687c6c193c4 GIT binary patch literal 997 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85z0F84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|6^CdTY00|UZg%ZeGc8hFB14o}!Vpe$^E zfx}jv+F@(ZV9>yX5x^yc1GtGX-9Q!?ak8o`py=k%W@BV!WoHIP6o|Eqoteo%2P7@1 zq6tiSKx;S{7z~;qaclsN<3*rIZW74MOUehkLgTGLQ-xl7E-1x<Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#NiU=a?j6C&q-A{pO6)$}Fi=cwl58C(dhVYG`0&VQ67$W^54!EDl zBn-sB?&9IkP0Y;EO9#v7CFkcFL>dUQu>-w%&X$RhjRVYJW@Kk}VqlTHv!zKq-QU*#G?3z%V2aK0m zV7xqo#0#^~?q|qR!U~KMKS(&Sgt8q6MTvj`AIO(n!tAbvrI~4o6^6P7+8_}XVW@yY zaB6aCQL2J-YEemMT4r)$i2*20taxj%hy`dJJV`JCS&mFhjEqbi0U6(Fn1IemMMNPe z{tS!^OpOc;Oh7RPia!ej3pm%n2{rzpQN<<9>z-!if?FgG#sGXTZ8n3@yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#W|Ro7#Rg_osmd3`1?g%St_h9 z`o2w$#goG26%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6A{H#)2v=EmJ#9b+_wAa u#P`i+uVusXPu<#6oIK%4eYKs^X9y15{EnGk2UE-$}dm#WI=|MLD literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/148fc92ab76dab6ffbb59a544e9174ecf32f187b b/external/boringssl/fuzz/cert_corpus/148fc92ab76dab6ffbb59a544e9174ecf32f187b new file mode 100644 index 0000000000000000000000000000000000000000..90f7ca414a89be290599e5b559e50778e445f181 GIT binary patch literal 1131 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFp1Y@Awc9&O)w85y}*4H^s@m^9uRG_f=o zG%;r^U=|T+Fq|aJl(AqcP#aJmgMp_Zw*e;`b0`a&FjHu-p|F7DPDnbaXe;OD-xwQp^ZfoSc)HnpaY6h^!+&xwru02R;@t7Lmhd&$=e(FzRW? z2S)o{Um%zsu==V256D%*jEw(Tm<$*UBEf)psQNEt`~b#ehif`#!~B@-*70S6mfdLu_b#h$dGDrZr(z_<&g>B`F+WUf93OZ8QJuM zG7p_JeyjS1-(a~~>HNEgvrGho{Ql+r{~T2--FAP|?lzT^ozo<)hzb^)6cpV)$n2%C zHA}A1L1B^P!UH#~D`js*9JuUo^H0|cH?Q}?OV?jDtgW~(L$fCNrp|}2-7i$02_9T@ zApWJ8q2SjA)8sR|m$o>IeA`&7r#SUwUhK?0D;SsiZtJkR>b{QGfB}{Vf%#S4C60;1 z5Eu@slZ~tlc&(89^qv7rKC$E$6DsAI{-4KJmyJ1m9xL0CV4LUylfDai_Mhgo?)o=T z#5aGBTfn61)TfyXgx=4e?jzhdQ}VlXXdRD6oKl`33zz(!m0zqL@iZ71bflVXHPtCd ucjIPK{c7qSl~AO8v6%S;gMkc7gSA#u!`jLGPeGx)|2y-XozFD1Gz|crg;~k~ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/152bd97b8a6e893d704db2947e31f2e7dd7f9c63 b/external/boringssl/fuzz/cert_corpus/152bd97b8a6e893d704db2947e31f2e7dd7f9c63 new file mode 100644 index 0000000000000000000000000000000000000000..09c1daf36369117262fc808c00b3644307af8d6c GIT binary patch literal 1046 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO=oCdPCFS)kRjsw^M}b7-?Mva+%> z1FZtFma#K48R&qd1yz7S*M#o6CV|Ynqlb8aBI(z6_jGhO(n~HXK~l^JSDc)anVMHpY>2EQ zKe@O7;u$^`F&2@-X3x4N=P>GN#|K9HU0)!W9l+npq}E2>f7KoO)sfknzd0%#H! zFo;+fuT?U!G8%BOv86Zi0F$SI0Z55Fi>86Pf$9R~1&VMd#n1H!Jbu#}`kdFO68~^Qmr5>>B`F+WUf93OZ8QJuMG7p_J zeyjS1-(a~~>HNEgvrGho{Ql+r{~T2--FAP|?lzT^ozo<)hzb^)6cpV)$n2%CHA}A1 zL1B^P!UH#~D`js*9JuUo^H0|cH?Q}?OV?lhK4<4M4J}Q>+KLM^G;5M?>U{Xx{X*rL z;K4-);$Mmx3VvNMO+K@GX^XSSw~e)Wic?SK#m?Nbf^oU;whpVS?(2AKUE(ac#e_={!KJsWDxPq-{TfAsXFy(<^rMj^QZd=H_nv& oE?vi?5vP@~ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb b/external/boringssl/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb new file mode 100644 index 0000000000000000000000000000000000000000..d435368e13f6d71e85dc861d34363d0ad60228bf GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krUmZZS4Fo{>m4`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZF1=nXBf{aiZTHiO t@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLI9%OL9YM+ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac b/external/boringssl/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac new file mode 100644 index 0000000000000000000000000000000000000000..4e5cc3b344dc7e2dc1d4db91db8021b13bbfe0b6 GIT binary patch literal 1850 zcmZvcc~DbV6vp$GEQZaP7(qm$EP@C*FF+ckcEpTEtOk_g0#<|=$b*=Z zZP7uQ7BzxfWvuAb1<`^_M{q9!iq#{83a&%5W{@1Eax4p^{u zu%JKLFcd*iPDTSh-*riIBDkf!lj|I1ZpV- zLL!BMUjmRHJc{GYl_zV-RJ}n*CKEys&_}VIUFPYtb*5xeCt66VbB1*}JL+-=;eak@ zx0T7HHY9C8afnL45|#j;#ip)#Wg3dGI0FwD!p3GWaF1Vqw2VoM35CR$55`|CRJJ83 z<6SdfZQszq$oKu(>!aGa{?p5!_SIE=C;P*klJRJ5{?+a(uEaV~-2M6WQ~8=|3z7jA zBn`Z%qrLoaS}-Swg)o_Hj5>;b+QY_Bm_oni`BJ5`45J zVp~R%x)ePv1`X%|ORggaC%Ou5IF6xgGiZhig&_D+NTBZWu5f@_y)`CN=2WpbGlO)< z7b~Kp6p|2?!Q`+R8Q!eYl4_mFNH}KbRmRLgHmMyy>?-IAt!gV9p(u(DP)U=E$n&MMvvX#-2zh z62k;~g9slB?$npK6mcAB&qJ9Aa9FIgB4?`G0O&2=cpyvyKbwzj!m#8I-%q5_>Qj=n zB6$>Lt%;7dK$r~7g19lLI5!ZrAPD2uC3h9Pc{avp?83st&X2XSds)YF%UVzFygB#f zKKW7X!Mq7<&bnKR#i#QZ|JKyqvP>3te`(By;Qm-2>FZSc#jkcn zcrcEYqY-6JuKlu*U%Z&#_Raf5@5c5zIA#3T%OigOM;gbEXkF$XbbH!9!70fjcPwB5 zo^`(_blP26JzKgqr84iKFczLAH3oHMW!!s(Vh97NF6xD%p7&VIwrgGmwHz+Lp}6TI z8W|H>@y(7_2PZVHuFz~O`L~9-!kJgFzd(Kb!X+iR4LE@&&jgJ6qdSf=EFGXci?Cqo zAjnW4Kx_-P1z7{%8C7MV298>9qC14{0x=aZij4!Es7j_Rs|BSEP=+cTvl5L1@714i>uNv zN_mxCvs0^AesP@Ns^~9GSZaLzLx-nC_x5Q*fv2_eaJ|*Hxnzrb>u8=aEYooNG&VUOd0w{`H(sCK@p^sNtT|8kyAQU#sI0RGOb#Rpa<5ecu2FSN>3v?> s1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO=oCdPCFS)kRjsw^M}b7-?Mva+%> z1FZtFma#K48R&qd1yz7SXV754!N6e9gzm^Dfy}(5e4uOtlg3+vrV3>DbAxpAv#>BT zu{RiGz${>7WQj3|GSG(c4Vc>GGfGMdtn~E@vNMtN>$`h8x*O>w7nL9>W`rwF&dE&8 zD=9Wa){&oFTmbPCABz}^$YHZ*U6XSd^|a#yqy4Tg5KIqPebs;m7>2-V5_PeI!D`)vHT^ObtQuIKk9AO4lk z(`97S56V1r()g|F8-9c3YNhk<9?mim4D$Pz_y2QLt#sS{O}pDvPIgX{xFRZ8Y*J8k z`yjKI!qzOgMhAsOk_!*qu&$K76>;FQ!_7ZkFWkJ|3ol)N_4}Ni&os0&4Qned%+Rb! zzNz!!YxfJ4XMzV89f*G^W+?b|!8G~I?xiixBHuRF>M2e=nHM{APs0kv<-XfGtggDR zND&?8}pT}1>d>$*?kzkwX0+YTAdG?>?wC?&h(SVUb#5aGBTfn61)TfyX xgx=4e?jzhdQ}VlX9gjwwQl6mvo|Rv$9`U4_Z8g;?NO$A@YU&=9P^5ja7yxO7NU8t; literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a b/external/boringssl/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a new file mode 100644 index 0000000000000000000000000000000000000000..df739fc013d0647204303ff3c7817528957912f4 GIT binary patch literal 1317 zcmZ`(eM}o=7{B-KdM*6`N^1v0=ylLBV6@Mb59<~aI;I_DRJMsqan8~l?TxOj<*E>< zmdkAB=3g$G8p-T16B844#w{sKVJ`kbOs2^!I(1o$vD=hoOBO&A9p2HcmPFsbp3nFB zJ@51W9uSCm5b)2F1decAF)%~!D(so-1r1eDm)Mb5)*z&M1%q}*1qBq*O;Uh&?_qSH zl@z5;=?sN@0hVqLdKoiRNk&5bV9v<1ks!;{jwtUBML2$#cG{qForY;$5gCk!rOek%M4c3Ldmp&Wu zzbl{t5ReZl#L^XJQUa`~r;to0Cs0npVYB4clH$_|S#`Rt&liiV3f2fQhfB6^&M9zL;1NS z|CtvS$Iedot)Fs_S-~U)(Byh36*HCMn~-RJ7?&YXP?T>>E&f6PDa1(DLJgRcRY_A0 z;{Ws$So2-CV}yVZ#@a8QIO&?~d2Z+FyQ$x5x~8sOE&F+9c{~M)zm35LL|J!pU(7Y$ zG%u(C1R^G~Ad_VQQ8Jy$zfmT`7}wfgSqz0DMv(yW$&Jx>u3XsPq}}bh8(g{Lj+G~_ zelne?o_qCp>9-GP2b;o?AI}pV^qKvYW3BW=*~!`Ow+>hQ@bv7Z*2{k#zW!LpE#0Y) z(oAgVn>TAmy_YxNUOaNWI-@;5F}v@Efzd7|j~lrorw+C~`h1k@_Y5%&;_SrADqZzG z3%!T+Mk6fU#zuIqpYwWn_FuwDYy%rK+Zbq)_$9H;4)&Z1+t&7Vk622b#>s}Bh(rf@ ziP{#X9Ll7sgsvoKcLqXzo&eqE0R7VGn8kE#F1YutbMK?c&a;QMq@5o^9O5{A69iHe zL~&DA6bOHk&~J@1uj_Ds(jl%LY40%prP1QLtWTfyO*se?A^Ey+aWv+lUqPdZZGZM* zs$gc>KR>F3@swyjT67ImDnm(B{l<#Av*9UmlK;8S1hhdKsgyjPdT&!*EkL|RL&*#3 Za%)b8VHwF`f_6|Pc3`W^56LhB{sDM)eIft= literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938 b/external/boringssl/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938 new file mode 100644 index 0000000000000000000000000000000000000000..4595890a32bf5db85c1cac57815953299f858462 GIT binary patch literal 977 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OkCWC z0tS3+%)%xtT15+bI0}}%vh!W>jH!(0V1d4#U22Nm0*};~E1{;bQ zh=8o%66SSJ%?~LmEiO^;%uCiYls1qAi8Bie!NuKk@{h z&j1wX(qw94WMsH?Mk3kZ?-y}psj#}}`!+ciPYSnJOuVvZ;SHZ3E1b76zw}jP=jgZ< zp`T`{xtFz~d#=R`*6mq!g-f0tNm#bweZ!MZ4gPtm*WNaNUb}4K@fjzbBuqu-uASjF zNzeb($9Cs~VpGF)1KxM)HdKYL{q!zA`w~O%PLUrXqNX{* zo1>O;=Ki^6$-+~9&#qjpUMYDt^xla#m*OmfpT_w2=>7{(Hv5zI>~!A}OG$?9Q<*F$ za`XMO(7PzhI_sOST|Pg%?0Ox!{sgmMkAf|QEw99>Y2UV8A+p!#wFI+95KH0H)yB3D zEq1e8o3$j(seC0CVDKgWfcA^R>?c2&m>C%u7dL(|XnboR4-86KWflnou?7*3XBj`W zFKwE7-Tj8Lf`GsAj0y9v7|60&hsyG?h_Q$qsG5<{+xdGnYYLBG?W)?;9jDIt8SsPj z3o|nQXJIv922!Ae5-Q6N5?}$QE;a)z5MQ3f*uc<0e}V1-?KaJfl9B=|ef{L39KH0^ z{1Q;a>Lusrf&_~7i@^yfIZ+SDGw@qrz{JpCU;r{g;RuVnfvbTt8w-%lU|?-v$;P40 z228B%OpIc>ATx`BhL)F?qZ(S2TAW{6l$@$xlvRlf%#;!}{C*IUCwEY8tgT&VS%I ze!Q?Q&AQ>;Ap@93YptfYSFGj#fB101@0zp4hMfkr5*I?77iFC`6P)wHBW-bR{SM(P z?*F=@Vv7H)yD4oXX|Z~`iO8yHmtHTH5#jLMw)^SC_swRnWyA8BGg6pO-P%)}JmE=w gwd!Pkt)_;xZw>5}PTR7-jjt$~^O%`8z;EGt0QDhT-2eap literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90 b/external/boringssl/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90 new file mode 100644 index 0000000000000000000000000000000000000000..216621484d500e1a97eb28704986fa01fd7aca7e GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1QFuAh86}EFm9BA6RLe;1|ksqc->R;LyAg^OB6iwlJyLw z4J1M0%)&x&ard13q{JKrXGeo3MkQo#Fj_M(H!<=v0L8hO7;Z5(Ii8V7Hu(ERTv;lt zF8aPrj>VJ0?G+QR>{)oj=f?`?ZOkuy71=pDZbj&)S!(WOt>~U>@q%@GR$bweXGap2 zZFt}Cq*H@`p6a!?&7apUn|OT2Nhb+Yk-2MUxJ}aYKlQQQ`JmX;aNU6Sow^NG;cGv= zi_gBq(7RLQhlr@@%>!hTc2z z=2DzR@Y5Lo9^HQd%4UDko}KPnVkyb6eJYdXL~g!+7J3(DS!aFowae#cmtC(T*Pmed z=$Bcru;rCFHSOEBD@67hy_R6s2x2LGy4u+Gp~Y@?vzDYem9NAMzQiBUeo>hHWDB4HrbAmZ^X5)W*`MlAF}))0Ty7QVl%J;DUfF| zHZU~MU!c1{yG=8rq@=(~Uq87hM=w1!zXTMiddc~@Ac122VsPR~PSgYP4E#WP6?o# zqDtgM0ZiM>jg1Ut4~6plyv2mt4A?d`a-9Fbar}5;UD~@tZ?9O(|Nrpegx@u1iw!#s zY9%g&HZRILZ6-M9g-6-q-1;5DSKR+~N5vHXS$9*~NYY~UbQ6(P(=NSUEF;3kpn*x_tw9rz!NI`NV9>;z zv4B}bq#=HiFjK|?N1$~e`wX9ct6>7#uR59kDbP-i{om*8eAcGLVZs10wIsDDFSSI$ zv9u&3zbLb$QsIG-ft)z6p{b#Pk%gg!shP1w6p(9XU~On*W&j3J2AOcj3L`m|gNMsG zG3QrWeo@yzz+{DZry>zgj z^^)^*4I&MM+1P;rb)Fpxt#VY>e1ngg!_?2;b}pK2@wg!=`*ln8`8SKWjM|j+-^5*#G@S9Lv2Mq99V8A|uL@cw=?q|qxssxNv zKX@=52L+RW0UyYdT*B|dkr^0W8QORO-|HP8kb!7Z!;Gy)`|5S*G^T9m5boLW?pnUV90Y^DBcDaOk-Ba^Jib{)1 zKq*wuP})EeD1t#r+V#e^XIk8CLW)0(n-QpWbWD-Zjf`5_`|dh>wW;_9Lk6ZfAC)joS+y4@VLlr#6wHA@zr z@_TmWYV}IVv!VA+ytx!-5&Sg9zeo39fU?=2v}dRLmRL$MY@fX-=i7n8BC$1KKYNv!DEAVrFDuT-^AshE#Nj78)?)r^eZ&flw9Q+NbxR{=9olR#!(Qocb2a=zkbYXBMu TEJFBMSeTjEfrUv1B+UZ=R19@o literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea b/external/boringssl/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea new file mode 100644 index 0000000000000000000000000000000000000000..1c50fb0dddd4f15ecee8ad4b129c2456438a1145 GIT binary patch literal 898 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxB0$sKQ-yiCSn@-PN{dSrJoA$E z45bYuLAEjr3%RF4#ocrAlM-_joE;6C7?qH{!N|(M+{DPw02Jq9YGPy*xOGM%+2HRN zab>Bny6F2hITlX}w^vNOvS;B9pC2onw=uu;Rb=PrxD}zFW~sTCwW52j#S7N$S#^a= zo*hY8w&8ullTHo(d8*gmHh*5bY~t}5C!HirMdq%Z;WkOn|J28J=YwKX!*v7Rcj`7& zg|GeeE~SiKQgN_Nh#k6S?{RS?FDqWu5iS*Djx*U3R^W zTz`V)qhDsh!j@O!)U1t!!hZeip&03P?RK5~3_!56W`$b_k zBQq1j&nJwF8$TE{zBP~s2BWMpi-dt#gNVnojGx+W))q{0#U((!z|4|5;cKn1K{HeaP~I1XzHHip{_Z zq(Gj<*uc<0e}V1-?KaJfl9B=|ef{L39KH0^{1Q;4>Lusrf&_~7i@}K}IZ+SDGw=iH zRbX*9a5ZpdV*xT546F?-**LV>fN7JRiBU`!WL7cIu=4V9RKto=i}Op1l2eQIi&6{n zi!)2|iz<;51u$(hH#RbqJrv6G^A;0oGho})$Z`Gy$MNHZb!n0B4!yl%E&u<+hZBC+ zoGmu&G^mxh5Zb&b>$I8RoEIKxi*xID2w!pk*Bup8{Ab-wX(LIC)zeKxR!y^dy;w$s z!*kp2rxV{do4u9|%RhB%PjT{uC-v2KN~dkv-^N>%%z4Zl;J0x7jCYBjTI_`YHB>=B literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7 b/external/boringssl/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7 new file mode 100644 index 0000000000000000000000000000000000000000..fe6520c7b8fe171914faf037e500eca731804375 GIT binary patch literal 202 zcmXqLFlb=Xcx%wa(r~_sIb#8{h)9FsBw>Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#NiU=a?j6C&q-DA%u6;@HBbf# zG7HOq1r0h*Fc`?NG+1i^txI7BsVPY<%1bR#a4ap!$S=w)sZ@AiWFRNbYiMd{U}Rxv YVQOY<5e4L$X&D-s8Gu2QK_-UH0C`F4(pInJ)@uG==E{h3?aYH99%v!*RYkVR}pZKW8v7PT(p&a~T%uCtYB zF%BUSU1ePrwbexz5g1fpe?k%@fn9`lQ$z$trB{*GML%cOAJ(9`I_H~rzV|urcLp@j z@Y+exi3Yk`Ofwe?H2wmI#dIwLI&%tiJf3E74#v#lN8?~;bIW^o_DW7h|hyu zmT4p`hZ`ICMUZc7tekmAdrE4Joa8H^!l>kNYj(8Lc4M?1P{*{%qye0LVS*Jz8=UUX zxHICFf%H>qhA_6o2g&~Yrs3vn$2{s-x6qLT=ZvE@s3@_7;Hs0Oya(Jyk>OU%7gZrC z3#zL&rHV>YQafEiKddaW^VK}~1AL&mrYaD&^F=kl`)eTcgh9%(>Tlp@tt>X{_DDi% zRg$t4;R~U_urk~1dz6%{MkLvFKoU;OiLEw+D-(sQL5QZ3f@`~wRHara8c_uU2P1@a z3olM}W15YpZwAj`13y&zdDvjkgehtO0`ptgmc>ScpT)3p_TXFyOQ0|lg3XbLNC|H& z6OT8l9D^p{STmjC$QF!POJ>0!GqcS^mcG5G7sd8gLGzE#D_@=tjfO*w`E5V1o*y)I zt$AL&v43~z)=S@}25wvqeAHUvU(a;Cnz&*0_pbI$9D4nvOT4M0IOr$_#nigkLkuiS z1xv4rnW0v*D-7$6*G@v`q&to+q|+Bka*J{@n>Wu;I|yO0Sp#vd4MOA~gg4RqHQN_( zZ;7a?ZJT_)wz!nlz!$8m4f?&&q?#p0^Wtbi5@fZ5&;CM*cC^hLBA*nJf}xu6bA1Wq ztvI~DIrJv&jP1KU3N{0aL+DTD!mgt;+&tCo>2s9p+MP+TGpq;%g9%Cuotw~kXa&38 zv4zVYPl@-BfA4wlsAbv1aE}jG83Gqs21{s9D-DUDu}++Wz{0Yz9vjNV7{Jh!kabW7 zp0qo?YM%Z-M@{_m-!M8tCLu6#^?K-5(~;eGe-C^q+xPI(`=uX#mB^Kd_0>zyhN~t$ S6Arjln!5IG=;#J#edsUokQ#&l literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/1a75d3e2d9ee4c34fb8d7506be6b2d762f6215d9 b/external/boringssl/fuzz/cert_corpus/1a75d3e2d9ee4c34fb8d7506be6b2d762f6215d9 new file mode 100644 index 0000000000000000000000000000000000000000..dbac0f398fd07dc0ed3f71a6b6bb13e5da54d4cc GIT binary patch literal 1109 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWQ{8<=28YEfQliGpKkNk)EAW=W-j zyODvMIIp3pp@ETwp@pfLu|*V+Yi3|*WM%*cQ3jbWO}a!$<2Ov^9I%S<#BGY|n; z#m>X)n_rq&l9-vN5SE!*4tEz1!d-t2B@D#C?&9IkP0Y;EO9wknFF8NgAksjXjUDLC zbGA&3Y#d+)Gb1~*69bFnoh?n`>HfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhlgK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*M#o6CV|Ynr2GnG_i}?&^RuupGqE=qWWbDJWMqjkh%(TI z@eP>TiEzHRHpM}YQ!9X6wQ)U4MdV`49 zT{bc4J>N36mVIs9wmV5`S5%|Efg(tO0*jP^1W+dzFeF$QuT?U!G8%BOv86Zi08^oX z0Z55Fi>86Pf$9R~1&VMd;_y!nT5@G>Vq|1UwKz9#q2Kbz1fPxncD_;%*!BFreeZz0CT&;Be-NRWXfxG-wd*P+)uNu}?T$rI*lYCR>!`JQ? zD$fKDE;w;yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE}>D9&qOWMFD!XkcOh1h!G)yoMGA7BGI4ffK5QVg@1*3whmB^FxYCi%S$d^OE%p zr41Sk3?xBP%)&x&DfgWGq{JKrXGeo3MkQpgFtRc*H!<=v0L8hOniv@wZk>@xHu(ER zTv;ltF8aPrj>VJ0?G+QR>{)oj=f?`?ZOkuy71=pDZbj&)S!(WOt>~U>@q%@GR$bwe zXGap2ZFt}Cq*H@`p6a!?&7apUn|OT2Nhb+Yk-2MUxJ}aYKlQQQ`JmX;aNU6Sow^NG z;cGv=i_gBq(7RLQhlr@@%>! zhTc2z=2DzR@Y5Lo9^HQd%4UDko}KPnVkyb6eJYdXL~g!+7J3(DS!aFowae#cmtC(T z*Pmed=$Bcru;rCFHSOEBD@67hy_R6s2x2LGy4u+Gp~Y@?vzDYem9NAMzQiBUeo>hH zWDB4HrbAmZ^X2e-Er!Sp8-EeT9}dXKMSh?GmrwO5m|na01Gf-u^Cu_ z6v(p}8yFhsFVJ0}-KLpQQc_^0ub*6$qnDnVUjm9(z2y8{kU+71F*pGwC+Y!t27YXc zK+Os)?gp*~&J9c&Zw;DQ8Vs7)Sb%~I2G$0aY#iEbz@*B~#3-fu?LpcnHw7!${q^k`FV>8wHdH&YUDWof#dk`!n(9~ zhu&VXmjD0Z!wJ7@&K4VX8q`W$2yI@Jb=pjD&I^yU#kuu6gs-^&>yC;k{==NHfLTPO z!Ell=Q^o>Ep!b0pi^DMETMd)Jx|`BQk`}9{n~1EMcIowE84(W8ZM&aNeBW&LS~e{I z)U7?m$rGN`SKBF_wq<`CZ&5PmF>`?5!u2!WC4OqLZ(>rN%>UGYSB-Q3ccD2upJ@O9 DgBw$y literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7 b/external/boringssl/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7 new file mode 100644 index 0000000000000000000000000000000000000000..362abb3782863de1cbb0961c421679610ffc5fe7 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#kuY`F)|9=IwO&6@b`#y22&TjwCGG z@V?SMd}L9wafx&iMybsMU}*M52z zpM8m;cc;h?5mD2d2iz7{7oC{6|7584*$dO{=BTBdxqq%%vhbAOvnyAtS4y4@y?5fx zr8tY=r!oFLy8i-{&Hki4JKeX$Qj%f&R3^)b+&idwSm(R~GyIx1GKf&_R zFSB4_%PVne+P7_2i0n0bEy1i2#8UWlwXy9(i{0#IElG1KUx^ufi9ewIqA>f(PbOwY z2FAsW9}F7b8ps2KQC68n!a%G+#N%1UPwh*are1fyp{yX_Z#-kd{3`~sAO(CZVk{yD zs%B*LcK%+?n!+PkyQ(&I$Eh=Z2K*ptVMfOPEUX61Knk2bWcfh?EWkv?W?%(UAkSiK zU}&JfKzD(5n`TByNr9EVesWQcUV3VN2`EzalJj#x0>%2p;KY-hs0ZX3_<{5)u(%tz z8aT7D0GSL1)&`br9NKKaw8_rID5eWCs~Bild3iaiVMVFM`K3k4sm1z5sRjAPnI-u} zmB@(#n6{Z48yU(T3g!8EiwU(Eux)DOIRAm;`0>KJw0DQzUa^+{|KY<4ziZAG8+IDh zN?ZtSUX*p(OmNN%kF>?P^*e;Gxc}>piYflH?xwVnq{Zs#CL*h*S-oB?Bf{aiZTHiO t@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLI6OPLBs$6 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 b/external/boringssl/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 new file mode 100644 index 0000000000..8b0fbf38eb --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A!1hö|0‚%“¥0  *†€00¯€€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0 b/external/boringssl/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0 new file mode 100644 index 0000000000000000000000000000000000000000..88e4e80f8b66787b3729c12e2a5e1b99722e72e5 GIT binary patch literal 1106 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?l=Ho&do;Nfyk%*jm4FUreIG!!!s z0a?Y)!|R)0npcvTnWqqznOY8a7Z0+#Bn-qrigS7R6PYt}^wR6=fiBid&d)W7G!SNE z2YU0IEfXUf2bjUk$j-?@p`GxWo{G8Xbzxt?(IYaCQ zA2o-mpTF%~G~42FLsItZmg@6w7I7K1De1q7y}Y+NV{sE>wm}nPx`8avYFSklkb^n2 z*%(<_*_nY>L0L=&Iv{C57GTgd@#iLjTn7$Mkn5TRGV_x1E09DCxIwDqvcwof8EC`!225@886_nJR{Ht{*_lZC_1!%k-Hr5;i%JlRO&Q^elXEgt^Gb>h zk#*!J7Z*VMz{euSB68U5S=ZzoMm_ELz-Yhg3k1^xR$n#X0l7+;k?}tZlL3Q)Jcy^v z0u1y95wE*!V$yrQWo#|`+PH0ZlGLuKMtuWCkOBo3DFX?hPA*_burOY$WMXAB;9z4* zZ{z`{LIVSk5_uL)19bz{1>B z`F+WUf93OZ8QJuMG7p_JeyjS1-(a~~>HNEgvrGho{Ql+r{~T2--FAP|?lzT^ozo<) zhzb^)6c{uZG%#trHE3dKFlb`VSimeI(qK4Am?>j{BQVb}G8NrE$n2%CHA}9Mi6bE6 zTMd&zlcIydBFTjZZdg~!-ikPI+2Q7&t`}}z?}b&DuD@zfTXA8AW=--5L=oToJ#GP$s#Bk4E)aS@f4Yxw<4no#(sewO z`JWo_vvKbKK4<4M4J}OrO9lf*jX0$|kk1wvFflY37<8OqFpyzs*#EtOpDspjyv#ZU>2BO#P2HmsinK2lvoQkz D8IV|# literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575 b/external/boringssl/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575 new file mode 100644 index 0000000000000000000000000000000000000000..27a2a39a76baf873fb82afef9d6b3f7daeeab93a GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI2@&27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwgqo?Kd#s^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhSIWMFP$-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fiZU=aG4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X9%2p-~^VOs0ZX3_<F^cJe%qj*NR$g9?YFJTfaeir0a%!=DQEEYcab`(=Q6+N1VP$1tZfs;IdnlCW z=Pf4GX27mV_Z#7K7Jfk|9|0!58M_U8O@#BScY3~lby<#o@|HFq9e%G8WHtaO0 zmADYvyeR9mnc$ok9tH;M(-!B}?-0J?{;xYKrufggo6<&-77eSXn~1EMX7zfpj0lJ4 zw%t!BzHc^r4Gb{Zu>4cE_7o>icv4?&r*ztu{cXHO$(+Z`0e%bD&v=*ksl{Fh0CYrA A3jhEB literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca b/external/boringssl/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca new file mode 100644 index 0000000000000000000000000000000000000000..51396035dde3318731ebe7ca1e682ee3acec967e GIT binary patch literal 1204 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLs9|4dj8rD67mOVIbBZ;_)owr}m{yQ?I+n zRWmYrJAbccP2mx&T~(X99nLJgXjuK`o*K1gci$llKq$QOAs8ab}Hfl1aAH3ziMiSCW{Srx2EzT5bq)7Z@D=xe-BB^cf55`bjO@(o zZb}8+YLs87{)~5tdF7{_~GdRzNKE$s@(fbvr1wS8^{R+!5`CLIPC%5YMqQkqM9rQViuyFn0A z8rP^SOO&ZIV_4Z7E=x9CrUu2K(|sUYoQvX=&5&){;f7(E0xp@ldkeCfZ1>YS=RW6u ze$W4$=K&x1(DXat$9>>Wbp)}u)jo2s3UvgFG4Nv@;73D23>Bg%7JWJda$-ql;Kjh4 z96^La0aTJwSVCYmIH5vos>!7g#ZM$E(VAv2-Dqtkb0CXfk*dpzC5KBhpdWS;kk_;dPfQZW&8>xd-o(fYvy&zh~u#|_PSZ%SFb+|k<+om-e zAu&cy=8<4Dk*2)-l_m=}%?Hw$58=-ObOh>PH5o>&!NoF3iPcFrx;zYRB{iVtj}pn` z6)rEsT4_eRfu>%694wLXd4;{wR#P^whtif%9+qyTZB~}zarm74VsbI3c|4vCjF4v} zA(yA&*-T(soWkk|HtuE?FeECunKzL)Ar>@Y6J!dfm3HdwVSDv9*EXmH6(QoT`QmdZ zLWsiy3=v_g1$f+#pZjC%FRg^S`?nLn?yMZMRMtef|LS{lM9`l0Rl+la<;#oq-JKok zf7kSjuc7Jp9qr#v^-GL_6vNb}%V*jh@B5J^@FR9e;Eqnv;XIZ&i{Rdp2;+`g7@?5O z|5oDMJ^2;eo}}|HrI`j-Yb39fk5=F~hKhXPcr1e;_^V(kfb*{AA98~WlOI6aUq5~$A1)}=ZACHTJ7b%bQCGNz>8jFO?R%+U^z@+v<*KfOadYvVvK~by%U6V+jE6YRVXiMko9DN)TnCX8 zf{{6`+39MqI<+Om-1AL|v=s^4st|DN5|sCM{F_)CJh&H=x@<#d-NY)V>1OlE);(8- z4__<4f3)NTcDo{3B;Gl`(a>0saYoqM{hn!3cyeoJbMFVC3-uokg#wx4Oy3AZw64qy zDBxOG`sNfynKb;-y~3YmRQ~b2Y#$6x`)=+^SM=$wy6vUXnLP6yOT8!SyOw_djMK?Y literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132 b/external/boringssl/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132 new file mode 100644 index 0000000000000000000000000000000000000000..532aae11e7fb23e6bf944c836c1182a2f12d7836 GIT binary patch literal 193 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 z1S%*;~=%SHfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*M#o6CV|Ynr2GnG_i}?&^RuupGqE=qWWbDJWMqjkh%(TI z@eP>TQ^ObtQuIKk9AMXD?XQx5i zU->*;MmGJR%tI%Q->SahH(0J#I{)tBEEB;XzkhiK4F(NN8gC7nSQ-SHm@^hIi-yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krU`ZZS4Fo{>m4`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|Af%L9wafx&iMybsMU}*M52z zpM8m;cc;h?5mD2d2iz7{7oC{6|7584*$dO{=BTBdxqq%%vhbAOvnyAtS4y4@y?5fx zr8tY=r!oFLy8i-{&Hki4JKeX$Qj%f&R3^)b+&idwSm(R~GyIx1GKf&_R zFSB4_%PVne+P7_2i0n0bEy1i2#8UWlwXy9(i{0#IElG1KUx^ufi9ewIqA>f(PbOwY z2FAsW9}F7b8ps2KQC68n!a%G+#N%1UPwh*are1fyp{yX_Z#-kd{3`~sAO(CZVk{yD zs%B*LcK%+?n!+PkyQ(&I$Eh=Z2K*ptVMfOPEUX61Knk2bWcfh?EWkv?W?%(UAkSiK zU}&JfKzD(5n`TByNr9EVesWQcUV3VN2`EzalJj#x0>%2p;KY-hs0ZX3_<{5)u(%tz z8aT7D0GSL1)&`br9NKKaw8_rID5eWCs~Bild3iaiVMVFM`K3k4sm1z5sRjAPnI-u} zmB@(#n6{Z48yU(T3g!8EiwU(Eux)DOIRAm;`0>KJw0DQzUa^+{|KY<4ziZAG8+IDh zN?ZtSUX*p(OmNN%kF>?P^*e;Gxc}>piYflH?xwVnq{Zs#CL*h*U3$G(Mufw2+wP|m t-#44RmJQ24b!$&?@`NY#)pkm!ZQ0+(Ta?Us%pBmiaQ%#TiJw~Rg#gXuLN@>a literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed b/external/boringssl/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed new file mode 100644 index 0000000000000000000000000000000000000000..4b58072a50626b70f47237dab8e88afcc17790ac GIT binary patch literal 182 zcmXqLFlb=Xcx%waVgO?4fLIL%O$JTOAqGuM`xY=WF)}f6WbbDQ5EGi5Ar1X|Jvv?U1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO=oCdPCFS)kRjsw^M}b7-?Mva+%> z1FZtFma#K48R&qd1yz7SXV754!7$CB3Eh!R0-1S9`9RqQCXKfSO%=%Q=LYHKXJKJx zVs9|WfLXxE$P!}^WuOh?8!)xWXOxr_Sn2B*WM?Aj*LU}HbT`sVE-FD%%m`PUoRgWF zS5j<S@OZM*Ce~AebJo`ldey2{UCdGX7^_GGH)}2gxe403)SA#Op4bnDm}+8C%P~Hg4OUB(*E5QQtrjq(Fg1 z%0L2W5*IL}SQxKWGO;omaImqZH}U{eseu7Vi9Cy@fx3a}0_6pYa3|yNUk+MwW^S@# zWCVpML#oBOc?K6$5vr5i0Q2pJ`}m8rD`^n4wvd zd{gJc*X|c8&jb%HIuQR-%uw*_f@$)Z-Ah}XMZRsU)l-~$GB0-Ko`w~S%YCp3<+iI#)knYC))zm#Ip-B5;F#zmLNk9Mq literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4 b/external/boringssl/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4 new file mode 100644 index 0000000000000000000000000000000000000000..f3bdb763d5938b595c8d87291f7972802c786d6a GIT binary patch literal 1850 zcmZuxX;4#F6n_G6|!yO=`VCW6BfC#4us36B$l|SV~I6C85$pYAXR! zECJh>2$~OuVmor86@wXl?%0-fE7xWRj@&^XsSb)ioA011xA7 zcv7J~eSK)a>>wt}V6bp16usKR!ZDaaA9H=E(piSlfdwz180j8j1b1z)=YqjNKyFtc zPCPjpoSAqS#RY3-R<27~$cfhE_T2M4+eE(C#NEHkKw3x%S@Qb?q7c~>~VO1#u2Q|45WC^JK2 z=P#1QM9IVZ(!^%yI zt8E8I8WoQ)Q-r9kIG=AOH}NnvioPWFa;hb2h>MaJuf=ikTUK> zVvz_Y(ieopIB=t0;!uneXh$B#K!MFgv(Osh{( zXob;Hl(Z(<%K~K}xCM1VC_5(rv!Ez)>yn!i0^d9v>pgB^VN%z}TIs#4W4YyRCwJbQ z`*L6OQT)NYi7fWITZ=`h5do(dxn>+q zD_dr`h4Z%^sGPMaB=*8zUq+u6R4fXPdr}%~UcKnR-;a|sT9J+Q{FnSO;hjyhYVr-u z<&7-~L6@&>{iMoo#igz*#qL=bPL4RC0N=(X%=O| z)FC26fdr8?*cwz4@J^^o12u3|dK29tbQg#ygHdF(b)r&1NmdJTD`1FuNDIPqgbZdv zG?SpDgFqxi42vH_1;O;2#;GF8$9_87s7Dc%^vd>~^1VxzTcapQ^eiXU18Xp9lK5_R zxlemE&OJ0(|8R2Li9fsC@4oTU1*1&S0?nD0&_3T@7uf5Uz2nZ=^f2xM`JgB#C+B_G z29;5tZBVL=B7-VZZ`7FdhCF)|)Lg=gi;z`!U3KzL1+FE)JiM+Mf$@a7@r4;N*I9sBE8=B_czNsqNR29P~dhgp}0Ez zqJ&%3Gds0r6&9d0P`X(`>});5M~49hg!K8?>2 z9!Z~2G+kKjzO(6OWS-}(#ZA|zcfMZVGi%Nh-tL3#FRJRh{R0EYg4}DB0c(_<{9 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4 b/external/boringssl/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4 new file mode 100644 index 0000000000000000000000000000000000000000..24181ca62ac282938ce8dff07bb92925846fdae2 GIT binary patch literal 887 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5G~pk}!~c&7g^C-vVYPMkXeX?ENf(e32)k4S3l& zwc0$|zVk9Na7UP)qRoB;@vVjl7#yl?9_MVC7}+?0VQ|it znUS5@iGfA(&Xy+ebbn)m=pQfTPS^Qejq(fSEBHCDXFo%=%28SK4L)iPQ$K&(xoEb< z z8R&qd1zCW>*#vX(Wd5hX7~$Ce9TeCgr#A^?<|XAZ12g_()H!5{->9wQ@5 zj6sxvHjHn;)Fz)%Qc_^0uV0XziKJiO-P6(CNH4jl1W7ScnrVin8N*4!zyPyiW?}{f zSO7S{7~y6n=VYell@uEy8=Rk9TmbPiABz}^$YHZ*U6XSd^+3T4@)tiF=l<_=c0SY4 z(lpT2jt`9XyS_j$Jz(`!10Il%gc%wCvoIMj7|2@zdCDxn*lZB-y2}RC(IzIn=Uc|s zvagNXb|*>gifYt1Py}gFV39JA0P5xf1}O{UwMr&dMgtBuw)93Gppy*@v^b1Fs^nQT z4b%-(8CVP!C@)Zi`v5Iev}9o6l7p5fm>U`xniv=vQZ3HSTj;kuGQr1S NG7Y&ma2l{R0RX@_4#ofg literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 b/external/boringssl/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 new file mode 100644 index 0000000000000000000000000000000000000000..dcd4a2c4a5d980426528fcb56e8ae250d653aa3a GIT binary patch literal 1663 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^%83F5&$A^qf=$&%9(qRRd*^AhWQ{8<=28YEfQliGpKkNk)EAW=W-j zyODvMIIp3pp@ETwp@pfLu|*V+Yi3|*WM%*cQ3jbWO}a!$<2Ov^9I%S<#BGY|n; z#m>X)n_rq&l9-vN5SE!*4s#b550^X43CV^M24Y}$@$ly+X6ERngJtxR^K%U%4TRa) zf!;i43-mk(n8D1*&g{g%B6(*^lX$wnu|f2YmvX1;{H{j%h4K~roY%9Tp<3mrtoa5X zHHWF6zwKN!+v0IUQugbX>ho_FaT&E4;0{huXc{yaG%#trHE3dKC}?8NSimeI(ttOF zxrC8@f(T)__oyGjO8ReNFYm3+Slq;zZP3J+ZXgQ`Jy}&2P?&RQvoW%=vNJQnSxg25 zV#E}jQpkxBHmbx34)6R%_K!2vKg-yenGAG5-W5~3kx$7dxJp+ESMM>Sz-*L476c<1Ex0ljFOT9D}DWf>`Wy6`tF{N?nZja zMI}gz8R3ePb23x&N{S7Ub>t@(7eL~Ok420{H_5jif}jM z@L&#F5yRYM#mETC9t^1#=jJW+TOOIPz!6v|fl4LAjBhnez*0(evH|~7V9B)KXXC$} zuhau}J-;vc@UMKHE+dMfPIG0`QjVD!E&|I`F9UznFt2?{mc9RIjUB= z?f$0SZ7L@_r%7B96)ZL>D7t-+*-K$-mRzHQ!Xn9q2X0tb%HE1NaM|JJA4qaw0VW3= z>422z?|R|p^dCy=nR^;mFfRAq)?szkeI0MDOPnRQm{2Lt^#44*y5aL!*^UI; zL>HL!UC6WlG^cgfzljEn&@khFYQW1N;+wz6Enrf0>eI{xLckD&=484gM4)Hi&!6ri Y+&EM6yL26oMx0U}Fl`FT?^$^r0Ketv00000 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 b/external/boringssl/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 new file mode 100644 index 0000000000000000000000000000000000000000..51a8f0904158e42e3ef27062a6861e101dc14ae5 GIT binary patch literal 1388 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|Pb$(Z){6hH(e$MOJ&rq#$ zRMvchkD9~O&;NEVnr-p8Au0QHOZE8%0|tWzYlAn7xQyDA^xwo@-dmlqxQQ{_pouZv zKo;l%SydL0`#H4P7+G1_nSnOyy@4>940J&9f-JzGY(jTslR#!(Qho)pySYKC`B_+) znb;c)GGHb$GP1-NL>Xwq_y$aE@);#11y=g{1=*QM`t{vC9o>!el8Z`^6f?HT3qw^W z=VYell@uEyv=}ro*8)?^Ge~M-7TWy`Iiauu6N(=^_CRsNr193EiKPLkEn@+*h)6^H zBw-+%`U&n0ES6CcTsHL+9Ik}MgPaivB{Zgt1&+Y%2Fh=S8Q*G{fFY_%e&YLvocKsd zbe;+8t{PfgfJuHe-mu=3@XKiBAd%k6CE&JNIZFiE? zuBb+R14WP`1r{j-37~E+V6d<-UaMqcWi;SmV@n5@cLD}{KsCVfj@`AeG&3!+!cZ5O pWq=~w!YWV^h2YfW(xOy_|EWbKnQ58Hi6yD9a<8$Z(trmT+W;gZZF2ws literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8 b/external/boringssl/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8 new file mode 100644 index 0000000000000000000000000000000000000000..3553e97f3fdb4d067709f41c910217103f7711e8 GIT binary patch literal 3 KcmZSRFa-bsNC3V7 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 b/external/boringssl/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 new file mode 100644 index 0000000000000000000000000000000000000000..01423b80ab9e9fd6fd33cfe1ccc32ed7035b4415 GIT binary patch literal 141 zcmXqLFlb=Xcx%wa(qPb}oUwp;ib#XuBw?nE1&+)HP0Y0hO-#=gFf*|-F)<76erCYS z#;Mij(e|B}k&%^^!NAXu+klgeIh2J>m?<>aP{4o>#NiTVcP%W$*8 zg9Mp{W#ED(sYQ7uC8ep33K{uDnI)A9?nVZ3;=G2Yh6Y9!h8Ct~#uiaPu9<Xj4ta3oLii3yCIWZ?QEx#x)Gtp4YKm=%&COZ$WZ+>ZBNn&Q6LRe;MIow@5$nKIb z5Cgl5hd(zlGe<8S>|(v-{9J=b17S9Hpf}IiGBL7ofEmn;?95IKERuJ&G>NDCn;B?C z|9B~Py3X%vlwT-c!OwX;`x&ZLj>?*E@KJM^`uW?=MYAm)HzZ}hZmB;1W)YWBo09&U z*vosXsTP=4!ZL4w4u-{ig8(=YAQAurJOyMdZeq+fXktt^kOg{IR+R-5NF3U1jI6Be z%s}r!Sxg2xAZbAsV01O1he(q^W?oW$g&rt1fn$~bsgV{^fN_Jg@~Z%&6`Iain3>oc X3^HJ*GcvNo7(^*(!}tbF``hvWRav(R literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79 b/external/boringssl/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79 new file mode 100644 index 0000000000000000000000000000000000000000..21d883a6eca61640a0173a24be364cb8f477e621 GIT binary patch literal 12 TcmXqLFlb<6`_IszX21Xd7cv7r literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 b/external/boringssl/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 new file mode 100644 index 0000000000000000000000000000000000000000..b941ede880e2a5d4c5cfa88475166d8c0e65d5c3 GIT binary patch literal 1088 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BguC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG`83-;k{eXW`)Ca!$<2Ov^9I%S<#B zGZ0~8wq{}H;q}cg%_~XF%u@)naNu53;)?48(x$y2s4JpP7@JsFx0Qv0ie1 zu0f=MFdMs8+tzcoOpI(CK>wbzWoBe&c4Cmc!_u@xJl)^eAo|BkxzlxiSEKww`3io{ z>)Fpxt#VY>e1ngg!_?2;b}pK2@wg!=`*ln8`8SKWjM|j+-^2#*tS@OZM*Ce~AebJo`lXaLK|Ey^V4ydMc->_aliu?!V{6&h#%;Tkq;^F$>KiD66ezGr8At$iasfkvh4ES? z6Dy+u2OC>@BM&eY8W@0-$g^k~s2iv*P+p)2cOnk|eeZz0CT&;Be-NRWXfEfxY|WBubWm6%x$wXZ>q^;M5eF_i-2Bt^!p-Zw z@Y3~H4Qned%+Rb!zNz!!YxfJ4XMzV89f*G^W+?b|!8G~I?xiixBHuRF>M2e=nHM{A z&kDxnzS}yiuDY+|t#ygBYnP@0xAOiHo1$G`@-~7@)8~11CDTHOFmczZwgY0Dq12M3ddH8b^GjsIP!GWQd zoS$nDX&}tT4h+F_woHs{9AE}BBRjJb1B>LHEluL-{>BE;KVHh6uJgMZ!el8Z`^ z6f?pVC+B3Q=9Ls1BJ0RcE-rus1RskSi^yTKXI+zX81=N{1Ec+}FAz)*Sbf!i2jnba zM#ldvOa=@F@*tiv3ozyyM7-{@iAnGIma(<$YvZ=vNm9F_8ubknK?)RDqzokB=^TY4 z1`SLaZw;DQ8qPN{XDnbA5os`-B+Qhtz!8`ofodfJGQQO?0rRKoWd5fH{A>oQ3zQcq zw#~;Md^w2R%L&fD%uS4p45=39<}LJF9+}{?@!!r@>H)i+-*HOEE*iuM4KhXLc`baRwJABHsZ1C{cL; literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436 b/external/boringssl/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436 new file mode 100644 index 0000000000000000000000000000000000000000..229d9e1bf0195d3c97c5fd8de92632faa6d054bc GIT binary patch literal 1081 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?+|g|l$*a5*RDWTxd8USYN!hPks?Wb!#AVc`r2i)N^4{u<#Z8Ra22G6V2C_h_WmQ=~4(8Bi zV`ODzXJ&-6m<)74(t<3&pld>RU6Vj&UQ&JqvU|Bfs`*)1n3>oc3^HKGFfy{l7(^Lp z!}tbFZSol{Q5Xu!e7mfpw%OoavpASLoF zng;3ystc4CD8ikH!#_D_$(6Z@k&z+Q?A*MCe#;{hd^Y~u`AR)t*Yo?55BGncv(upM zuY8^^Bb$Cu=Ao0uZ&ly$8!T5VoqzXmmWg1H-@m;7pQCD}+cxcPQ#si=P2!5EV6jO- z(d~oGUJ6^Yv(Hj;w-tv zgi3j)|L5`54WGx#b|ly)y1=CGLZ1DnIjy_?O%(CX-{TfAsXFy(<^rMj^QZd=H_nv& aE?vi?5vPrE>ziNtbL0N~`xL@5Q_JD*;sLoU_2-%m={X995(Z*mck%G&CT8a7rGp)( zmz0;D- zrX3&XcYT3idcf+d20S1)3NtePXJIm6FpvlFlvyMU45*OIz$prm%w&McOanEYIhMlG z*#pYb*{?OAbfykTXJQQ^UU%7K#H9Cp%h+1>wQ<|-B&l6djrs5V+V{A2)*V0jiz19fm{YP>aQVre+v#GJ8!Swy74aFQ@n#sWuR z)&r`Q2*~(W!vxHWs+0Mj8uGIls4h@mpa_p0XjB686)1JUqcR7aQ$ZP(6P#0-n;01x zQZ3HSTj;kO80fV?^PWNSHnY&~XUN%_RVp&UXXC$}3-z;NPc0E%-lfdcH-8Hr?rzhA_arNZi>@7v^9JSp5>G4aZtg*SYDtZ?4O{L)vE zoulJcgnpW(=3dr{?zt8(Shr`@6)t&pBw^Wx_YF@vHTdVLUVGd8dF`@^$7h^$lDNNV zcPI;_e99|H%*;b7pG-yOuASjFNzeb($9Cs~VpGF)1KxM)HdKYL{q&Au=cVl4c#$6> nqNX)B z&Bn;e%E+e8#=*`EWU(_d8R&qd1zCVW*93808r*eF0-1S9`4!0S}KrlUE^;H8NkOzbr z8UM2|888^ggLuj;!1$>b@w&?N|3M^6v5h$dGDr zZr(z_<&g>B`F+WU`@hfGY0&mpK2MjCO+P5}&`IOBs&BXrfPr2M%rws+ znTAqj{ZJFJfB_%SjVxTk?90_k=ifb?Wg-~l_b>1N=crogw)>lQx2c@$ zoF;KaRIu3Oc0tiWW-o=USuAYu^v?~_3QW>+jSdQnBo`jIVO=SEE8@Uqhns)8UbuO^ v7hbyls$p%#g&CSP$v1UAeC>Xr@=WmHq66_S#S8_%E|?~t*}b&I*|iV=n-L?+ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad b/external/boringssl/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad new file mode 100644 index 0000000000000000000000000000000000000000..ccb2275825aeacb3d5399e63a05a9eef0eb54f04 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZtX?mc5#jLMw)^SC t_swRnWyA7M-P%)}JmE=wwVl#wTlTl{7A12YGY9xBTtDMo;-?mSApiphK<5Ae literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b b/external/boringssl/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b new file mode 100644 index 0000000000000000000000000000000000000000..15d763e75297c2857f9753ee2b42ce893b02f688 GIT binary patch literal 1373 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&e2?c8#|hO)MY@ghAJU8ul#!ngBE)dp}DcU*ySX170>xtu~Lg z@4SqR+^h@+o`&28oNUaYENsF|p}~g227(|CmoS%metvpRs)A=;vZ1PhGDwhFSOzXw zl3J9PTB6`sT9T1plvz@#;BI6fC(dhVYG`0&VQ67$W^54!NzBYs2+K?@hr5dh*HCV}s})FXc|x`CX0j z3*{^LIj?6wL$%6LS@R7(Y7SFBf7`iew#DOyr0mx%)#u+V;xcMe(ti_sd2h7=13Z99 zjVKLZOfdjK#^NT%Y=b7obOTwS>t$70Kz`=XW@BV!WoHJu7Rq8W&;dycvH(NBi9Z+B zgG~aNc}e*d$X@0Kspe;4VP;})Fvx%z!^p@IV-RI!pbZgVH(+X$&nPJ=u+rBr$j(I4 zukY^Z=x(H!TvP&6%gS!R2v?k(lbM=VQf!E#hDssRtkRlg zifYt1R0JtdV39JA0BYs}1_le`wMr&dMgtBuw)93GU|KdX04b4Y(KJvuP+g$BKoRar z9A3&nOZ3c5jEoGa7U$+I^jjX8;Ir}H&R6OIyPn^deE3&BPnVHRKPdCiN#nPwZ}<(C ztCh}Qd-rgbiC~c5zr6pSqiUtw?r+-NrgE}#n#2`R!D5pFaGuk^m3bMNif$id_EOlI zCD#bg#)=LKizF8wxM5u>dn@9=Wrv%8x?Z?>y%$zpy8fzRZN-Hdnl;Hcbv}IUexdSA z@Zh2Y@h`;;4Vr*OLkQJ#^c!HNVb*|@I1K{eG>s^D7(gYD;MWDyO3-PU1s)qNdrtxKFGx0p~V&-DL1zPjP_SlNyQ+e8yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxB0$s6aS8Lfr{;$gl@^yMc;+SR z8A=;Sf^20L7J`er=j10P<|sHj8Z{tHkx`;+$Ubl(z7NrvrHnJg!A^Zm2XyC};#>zl7#K0mwcdL6m` z1j|Ri%z}k2uf(Zo-?m*Lve)Rf1hYmEOX1Vi#iS!EUp1F;4Xk7pS_wJ&X&dfokovVwrW@r()cuNcUJ6!5W# zv4|X~nvv1l`Fk~M3Xfpzs@l{Yr_T5p@Pnj<85#exuo^G}DRBCb8bf8ph(qA&d&u26zdm*6HjuY9*}3?2hyv+ z;%?w-;LOGXWHK078(6Y&XtM#+COZ?Om@deyVxVE=<>jb`6{QyEmlh?b7V8(K7UUOa zmgE;zA}0!9+GcKSWGH(ml;`IyCe&uYwyBZh{0ENX#|!Jy-W_^-#ajOVhYu(Gt~pz5 z*lAEJaUryMQPycQ!8tEH(iZ2|?-0J?{;xYKrufggo6<&-7OSV5h^(4+>Gfh65f0C7 xyPr;c-)#0;HZ1?ttv$ub6Q0yp+bNy4Wq%uQQ8MQ-bAaE%^)ucjermB70succLOB2c literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b b/external/boringssl/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b new file mode 100644 index 0000000000000000000000000000000000000000..550f4c907480864ce9b8fcc630653430ce068f12 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2u@fyQ(&I$Eh=Z2K*ptVMfOPEUX61Knk2bWcfh?EWkv?W?%(UAkSiK zU}&JfKzD(5n`TByNr9EVesWQcUV3VN2`EzalJj#x0>%2p;KY-hs0ZX3_<{5)u(%tz z8aT7D0GSL1)&`br9NKKaw8_rID5eWCs~Bild3iaiVMVFM`K3k4sm1z5sRjAPnI-u} zl?J?8ZQt8G*f=3+o4K)(q3oeho}agvP@4hUrbdqQA2^O5FRV*@cj)aEYx(~lKAiBo z=4`QHhe55xh0x|jS*Ohe=e+PpTbx_JL->mOzwW4*;y>$dN*hU9te$QnvTB;u>%}r6 z9G=^DKb`o#+3dA!SpKP7dy11MJgKj?Q#x(S{x;sCWX@ye0KbLnXS_@N)M76L06R)S A&j0`b literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd b/external/boringssl/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd new file mode 100644 index 0000000000000000000000000000000000000000..de773a6bc248397f363a081344789e12480414fb GIT binary patch literal 975 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(pFrjI4eP2E2yc2Apinp)72|Ok7rm z0tS3+%)%xtT|jfS4MfC3 z4MA3L3G=$A=7$uO7MCb^<|XSHN*hRm#F>SK;NtE%`ALa63eJuOO^ix#zwk0LGO{u- zH!<=v0L8g9nVJ|G8E&1CNH+NUMO;}btS8RpDzty^GJj#L&A_CFRfi>r%HOx%AmRQv3O z>2`C}QqJ5z*DP6h%J12gtJNzd&xYPR@#a#TMex%Y{~q0c0m^27(w?2}TVg56uzf0% z(8XO~^CBiEl``RJEfu(0KoI5q9twkt&T8oica)(B!Le7f4$ z_MydYc5Abiq&bzZ!~zVy#2?UpQJDSYClfOx1LNYx4+f2I4dj6#DXYvPVIbBZ;_)ow zr}m{yQ?I+nRWmYrJAbccP2mx&T~(X9g>`Ax4et&az%*KGHNCxJE&u<+hZBC+oGmu&G^mxh5Zb&b>$I8RoEIKx zi*xID2w!pk*Bup8{Ab-wX(LIC)zeKxR!zI~da;ZMhv&B4Pba=_HhV1_md~7#!hGu1 np5o*QPwJ~xC-ZAHHLQJWV5fB2mi=vfMai7U%)9}93)cexPK{ae literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06 b/external/boringssl/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06 new file mode 100644 index 0000000000000000000000000000000000000000..0c30057b58d7a7bee475784dc27ec71a181aa971 GIT binary patch literal 1039 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyD6gcXG}TcdBfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG`834yaaf@NhXN=47Vj7v*Ip8j2Z+ z0Ikww=i&9uFU>1S%*;~=%S~ z4pTpW+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO=oCdPCFS)kRjsw^M}b7-?M zva+%>1FeFxm<)74(t<3&pld>RU6Vj&UQ&JqvU|Bfs`*t|n3>oc3^HKGFfy{l7(^*( z!}tbFZSolWbR zBE}+e*z8%?0PFeF$QuT?U!G8%BOv86Zi08^oX0Z55F zi>86Pf$9R~1&VMd7Gz@ePYzmgWo}|*WJt9*H*cZe^2h|AjsJGOQV-bmTv77jU->*; zMmGJR%tI%Q->SahH(0J#I{)tBEEB;XzkhlEKS$L{x82{gyG`X}=QN2cqJqUH1x2?H zGJ7d(&5~<$P*^0n@PI*sLBj$Dh6V$JjuQ+9GAs@Izi((_X)tJF&X}_kl8rPu3^T01 z)u>M9*J^55YrxCQmSJ$ix>EL5#DU8WH~)0KaPxXEymb9l!`g}qGd}1f*J$4S+WkW1 znc%@i2jX9f847+~Fik$QdufZa$hVEPdWus|=Ect3vx0HC@3s!BtM2P~YvU}r#e_={!J9|&EMk|Fp0A|^=ak;q4)Er`v^DAl>9DT l$D^XXO{GM?9%!TTOKe(%rbfnz~0N6lq^91^{lPL*W1b literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91 b/external/boringssl/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91 new file mode 100644 index 0000000000000000000000000000000000000000..16dbc90c0012608736f32f005d1fa5bfb2ef16a4 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krUo7#SIEosmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKL&idwSm(R~GyIx1GKf&P9 zFSB6bE0%F;+P7_2i0n0bEy1i2#8UWlwXy9(i{0#IElG1KUx^ufi9ewIf;qeJC({!~ z2FAsW9}F7b8ps2KQC68n!a%G+#N%1UPwh*are1fyp{yX_Z#-kd{3`~sAO(CZVk{yD zs%B*LcK%+?n!+PkyQ(&I$Eh=Z2K*ptVMfOPEUX61Knk2bWcfh?EWkv?W?%(UAkSiK zU}&JfKzD(5n`TByNr9EVesWQcUV3VN2`EzalJj#x0>%2p;KY-hs0ZX3_<{5)u(%tz z8aT7D0GSL1)&`br9NKKaw8_rID5eWCs~Bild3iaiVMVFM`K3k4sm1z5sRjAPnI-u} zmB@(#n6{N08yU(T3g!8EiwU(Eux)DOIRAm;`0>KJw0DQzUa^+{|KY<4ziZAG8+IDh zN?ZtSUX*p(OmNN%kF>?P^*e;Gxc}>piYflH?xwVnq{Zs#CL*h*U3$G(Mufw2+wP|m t-#44RmJQ24b!$&?@`NY#)pkm!ZQ0+(Ta?Us%pBmiaQ%#TiJw~Rg#c_gLBRk3 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3663d7a7c4840fccf48c134a13eed5156b44055e b/external/boringssl/fuzz/cert_corpus/3663d7a7c4840fccf48c134a13eed5156b44055e new file mode 100644 index 0000000000000000000000000000000000000000..9368c7b1fc47c7e306a775b5972e6b5948a31f69 GIT binary patch literal 969 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OkBZ+ z0tS3+%qA>c!tAbvrI~4o6^6P7+8}9eVHJ>wL4!d9P?Sp{I5oMnC{@8ZwWuUBEi*Z> zBvrw&v?L?HD6^!}Ku(<3z{tSV$k4#V00^SQdDSfpEZ|%NCnQTlgAK(DL_k(>3G=$A z=7$uO7MCb^<|XSHN*hRm#F>SK;NtE%`ALa63eJuOO^iy&eqm%~U~XdMX8?+GX)-l2 zGBVscBav+I_lvl)R9Ic~eVZJMCxzQ9CSKXI@P^Ni70%n3U-~Mtb9CH_&`-0}+{;?g zJ=fv|>-Ma=!X?j+BrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~ zv8my@0q;9?8>+(BetH+5eTkuWr^pWxQPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w z@RZ-PD_5&mN}dh9cjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb z`sQnw&(AKqUPrD!!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+ zi3J#Zi9ewIqA>f(PbOwY2FAsW9}F7b8ps0!QdXHo!a%G+#N%1UPwh*are1fyp{yX_ zZ#-kd{3`~sAO(CZVk{yDs%B*LcK%+?n!+PkyQ(&I$Eh=Z2K*ptVMfOPEUX61Knj#h zLS^|u0xZC^#b#gy;>)ub8yFhsFVJ0}-KLpQQc_^0ub*6$qnDnVUjm9&z2y8{kU+71 zF*x}oC+Y!t27U_+m>3!i3_wOG9AR-ca5ZpdV*#=m46F?-**LV>fJv2|iBU`!WM(nY z(DL$fR6~nWi}Op1l2eQIi&6{ni!)2|iz< zhNWTu_XdWB4NWW!22IQvb9O>?JX@JL&nTfam2iu=FrsF>nE>uyRLNm{I)ZX&X3 z+NIZvWkfhUx9xs9@qM$|YuT`T=8P2PQ@8dMCr@}%U#&WsU#qEM?OOvorPH?TZ{sUU P<~(NR4e(pIe#SchWz1Mj literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9 b/external/boringssl/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9 new file mode 100644 index 0000000000000000000000000000000000000000..07673247f304d7f5dd9e6d5e987f9921ee68bab0 GIT binary patch literal 1569 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%See)}V={!Jvs*eF3wGNQ2=dVWx})j=-n^#Z5rQ zw19k((HhE#FhUA>g)Vz{nLxe7%y|uvf_6(BVn1yyf zLr!X}z@+8}kAKu4$p8mQ{3Kx#oKAd_eFIC!C8VZvYhdCZsC3Q)&3{cys+0Mjf!KR>y+z(AG_xirfrt~6sHwKxN2UOpBv7Lmhd&$=e(FzRW?2S)o{Um%zsu==V2 z4=8Mf!6gJFJAg|FM#ldvOa=@F@@yDoAy7H6n1&@2q7sKP3o!XKhRl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#NiU=a?j6C&q-DA%u6;@HBbf# zG7HPV1xr$k@={9_97{_w@{2M{Dit0W8OVwA8k!m!7+Dxvn3@?|M2Yhn8JZaw7=Q_b zD1%I_R&nrfWhLfhrsWsqWhNSm8Hj+aV&~!Y%`eR>NzBYs2+K?@hq;S~i|aVTT@nUj zV0ZEG=O$+6=%s^Y^pf*)4I&MM+1P>JJZHMt5JTTd<8$}_3US;RyitbzQIS$Y3k>1I~UEic-)Yb{ko<4{F_BwMr}&^Z(=X+ zt|rOD-HMz7X zRlzy6s3bEjGdZ!u0F)?Jyfs+F(g3s&o+y|y7B~Xa11LcRWPGb(0y-oW5s9D}G%zwS zH8M0X0mhpFFa`}R3@qSW11Gr4z=;JKSzN-r?y319MWw|hpyZ-wC~Y7Kav!s>5M10n zCqF4MN5R?Apovil*~5&i49rc8{0u;GE~X|%MuuBwB$5sOVsWVIWd5fH{A`^2zt7pJ SsiCE5VE08_St_h9`aS?|ddT4b literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0 b/external/boringssl/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0 new file mode 100644 index 0000000000000000000000000000000000000000..8fa5ff7fe30b014f94b20c1965afb6b896032adb GIT binary patch literal 1851 zcmZvcc~DbV6vp$GEQZaH7>Ni(Sp*~Gys$J#?TCyb}ME3*-w@4BQV8C)2nCYQ`EdEtT}PIMZ?5>7CRfhFP$E}ED?aDhWD*j%c+^o$XP0^U9Gyv_(Fqr7RJkL%oE>#}0Dn-I zv)f9AMjMhos5nHaUkOWq%V3h%yfO_%7_7ku3}Iq3Xt?0lAFX54<3b_%6Mffx<03@nUiF`6h3gb_IRIsz;PBi-Umwi^Jo#Rm_9N#JkuwM`h2{NeivWmY$*OxJ;`4x+TJZ3KAV6#jwuwrD-WgSCASaGWZ=yPc>H;wtFp75XXUCnh8DX3S@&R#fZtnZC z4JxBP$DmXh#RgTD-l#F@4f&2L$hm|STWG89y6fbh^4&{-ad=%b4aVc<#usLqxz0M& zMpgAgV=ah9fI6ywjfHi!k9Gchc2U~nGccSGHQCzR7UlD{udi9&5hJauheD5QiN)0! z7b7@T-LunbR(^4u+a?<*OIm7t{X?gxMECY-QlV!_*Wrc|zn0Q19&KYd#;`2I?bFyC z;gJk)%XDG2U}w|KsC=(mi<_=b?|i+!d)AyM+}#J;UsToG11AR&g?ZO1gVrcJr}RB9 t>-MvAPFFXjJm3?Y=e8|AnzG$%V|e|C3I)>Itzo?VTUsC0jOVdp{{w6)S6cu8 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7 b/external/boringssl/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7 new file mode 100644 index 0000000000000000000000000000000000000000..03d905b85b2dcaee3bb72bdb5fe87685f4edc31c GIT binary patch literal 61 zcmXqLFlb;>cx%wa(qPcUoUwpeM5MuRk}y-o0!L;hMn)zk4#SLZHB1IgOsbRlpBnJ0 Raqj;1S%*;~=%SUSYN!hPks?Wb!#AVc`r2i)N^4{u<#Z8Ra22G6V2C_iAWmQ=~F6Pi?V`ODz zX9ijYWic7(fTRUkfMM5!=Dge{fy}(5{0fAFa}Bsbs`*)1n3>oc3^HKGFfy{l7(^Lp z!}tbFZSol-6)JiwhwBtrV6@-$1%l}TtFIdHfP5g#$oQXy$$-H?9>h~-0me{+h}T^m~C)1*Pcy-{#(}& zzK*xnCC-vtOsJG+`hOl@-SBy=Y)67^q6#V#bRbF0Nn0I A!vFvP literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c b/external/boringssl/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c new file mode 100644 index 0000000000000000000000000000000000000000..1cab2138538a42dcad23a6316da572dcc0e7f6bf GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eAQFmN$4HZd|a-8v(YZ1DGsxUy7O zUG#mM9E&G~+bbqs*|YG5&yN+(+n8VaDzbBQ+=|dov(((nTG2h%;sxvWth&M_&yFN4 z+wi{ONv8(?Jk@J&n?J8zHu3n3lTH$*B6HWyaGRv(f9hkq^Fgtx;kp6uJ9QhX!qg^Si7n=b;qeQeg^y?X<j9K4kep0xZBp#b#gyQXtP_ zY+z`hzd(0^cAI8KNlAf~zJ791j$V3dehDa2^^)^*K?244#o)w~oTvxn8Tf(pDzLa4 zxEeUKu>hG22G$0aY#iEbz_iKE#3-fyYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWME`wU}|Il1X1F=h86}EMur9^V6K4^s(oSxB0$s6aS8Lfr{;$gl@^yM zc;+SR8A=;Sf^20L7J`er=j10P<|sHj8Z{tHkx`;+$Ubl(z7NrvrHnJg!A^Zm2XyC};#>zl7#K0mwc zdL6m`1d~U<%z}k2uf(Zo-?m*Lve)Rf1hYmEOX1Vi#8bf8ph(qA&d&u26zdm*6HjuY9*}3? z2hyv+;%?w-;LOGXWHK078(6Y&XtM#+COZ?Om@deyVxVE=<>jb`6{QyEmlh?b7V8(K z7UUOamgE;zA}0!9+GcKSWGH(ml;`IyCe&uYwyBZh{0ENX#|!Jy-W_^-#ajOVhYu(G zt~pz5*lAEJaUryMQPycQ!8tEH(iZ2|?-0J?{;xYKrufggo6<&-7OSV5h^(4+>Gfh6 z5f0C7yPr;c-)#0;HZ1?ttv$ub6Q0yp+bNy4Wq%uQQ8MQ-bAaE%^)ucjermB70szQY BLWlqW literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4 b/external/boringssl/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4 new file mode 100644 index 0000000000000000000000000000000000000000..5c0b792502990eafb3ce5b1dee8451c77ee7e62e GIT binary patch literal 1111 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqT8u4TTK^K^!h2F8BQW^qf=$&%9(qRRd*^AhVDRT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Ve@o;cCC+1|P2-%(GGm%SLHEluL-{>BE;KVHh6uJgMZPfMM5!?z|>}%)F%h3W$S~Q}qnk@^iU?s`*)1n3>oc z3^HIQGAgpf7(^Lp!}x|wZSolUlUR}pOdnHASRp9{lspWK3`~s-4NO1@ z0+c)~3@qSW11A(4ji4!kOPJR^H9w@Nw73M67WE9J4J1MKG7AgA#DSh6Ev18f1WW0{ z*iyPMYDz~*=!TZWCv>1qj_^#y!GkTO^MF&jf_qMWQeuvRvm-EZDZwHGm`52|8JL?G z`5A!1Tue=jj10HVNF*El{UWX`6;>C0-zLZ6N#XX2iC6Y4yy5d>h4VJ%m%fVZ938hJ z^wTUg_p(-W&$W2Lx;?9|aLKbH3ClLTZ+OzF!9P#++S}&OYnM$tKI5d5gsI5fwKLpG l5;ODQd2N!O|EZ7d&IiS&hU*5r@6>Im3Sax_olW*71^{Z5E))O& literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee b/external/boringssl/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee new file mode 100644 index 0000000000000000000000000000000000000000..d3bd31da65ea1eb3f14d33ccf2292086cf4d4295 GIT binary patch literal 1039 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyD6gcXG}TcdBfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG`834yaaf@NhXN=47Vj7v*Ip8j2Z+ z0Ikww=i&9uFU>1S%*;~=%Shan6>Rk)7FzfkpDpmL~CZe`AB_A1~!j*ZEzI@(blF_&Kjqvcwof zDQLs^225@886_nJR{Ht{*_lZC_1!%k-Hr5;i%JX-iW%XGlXEgt^Gb>hk#*!J7Z*VM zz{euSB68U5S=ZzoMm_ELz-Yhg3k1^xR$n#X0l7+;k?}tZlL3Q)Jcy^v0u1y95wE*! zV$yrQWmJ`YZQQmyNorSAqrQP6NPz;2lz{|LCl@dzSQxKWGO;omaImqZH}U{ep@9KN zi9Cy@fx3a}0_6pYa3>aIV)aiBT5@G>Vq|1UwKz9#q2Kbz1fPxncD_;%*!BFreeZz0CT&;Be-NRWXfu55 zSbwWgoy@P*)UeiomzgcY;D&Xj?5&6cmmO~Y>3ZSj^J+5Aaep;+k4h-gzE}(ZwQ@tJ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33 b/external/boringssl/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33 new file mode 100644 index 0000000000000000000000000000000000000000..82ceb520c3a7349a7cedfc6874a11ef459788e25 GIT binary patch literal 992 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcDw8VVZ-f;e2lT<-b#={czio_WcJss_p+L1tkYxL`?YQC@0^f@5h(Mt)IdNu`3j zk%62zuc4`-fsuuwxuKD{Srm|KW?*P!W&j3J2ARlK1;ec3;Nfyk%*jm4FUreIG!!!s z0a?Y)!|R)0npcvTnWqqznOY7}e3gZZ2iaW`24Y}$@$ly+X6ERngI%nboS$nDX&}tT z4)o?ZTP8*}4j{w!93wM3vl9c0^$W5yk@V}kdpf!s=_MDHASq^qD^AYIOwB7PHbmBupIlr3 z@dF==7>meZvu9nCa~Sos;{&7pt}hTw4_JNGfCuC%VMfOPEKCLr2J#@DG7B)!8$`VB zvWZFW`IfP@>}%t;-APirq8jxL6hR6USfmUjfI7K=A;H3Ut&)kA(SU=EExnNkmhFR2L{OP=q@XhktU=k}Go)BO^nq#kqM4{gy{2_-y>Q^ObtQuIKk9AMXD? zXQx5iU->*;MmGJR%tI%Q->SahH(0J#I{)tBEEB;XzkhlEKS$L{x82{gyG`X}=QN2c zqJqUH1x2?HGJ7d(&5~<$P*^0n@W2i0O4(Zx2QE9@{L}Tq&Fj7J()CvjYb!3y(5y+m zsq^7$_Y0M0f(I8Jh<_<&DEM{3H2KW#r7g}P-!|6jDNa3^7dvy$3dZHW+d8bSy07D{ zb&0d&785Gvnf{;0S2uhfE8CG^o9F_Qz6*KwpXRjg`ZrO;H-C>?z@+NbrK>I)q^PDXcBO3>p!OY0c?8Lw#d1p(Lc)Gu_LG+K8a;NM3u15KV@)i7?*R!9YTIHy$ z`39e54pTpW+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO=oCdPCFS)kRjsw^M} zb7-?Mva+%>1FeFxm<)74(t<3&pld>RU6Vj&UQ&JqvU|Bfs`*)1n3>oc3^HKGFfy{l z7(^Lp!}tbFZSoliKW4yi8%wBxD7MD)u>M9e~PA> zHi_HZ)WFCHBXMUSC2mAM;^5(OCOUC*0TVYO(}^310t1VMnTM~uyc`yD&)b2CyNOW= z*`tiC48UOFX8?+GF@eHoi&w`?of5{ZD_-JV+muWmZl8E4St&!<{)=Jw*@-t!ZrS>! zT(U|rz2nPfyR#|!yr=emSKyImzO8QOcB_g1U!!BI!@52HdRHu6HYsGnql+cS^y*yN|n6FWPOYEG72hT6p%imy-5SzH1Y5Sh+ zm%KX|Do)M+RnRN{QG3aUWlTk1luaL0$Vl2UF*7nS0yC;NFi6}9Wz+_P1}2TShy*1f z(qK4Am?>j{Be38Em7Ji&#bnTAAPGvlf-FJ?0!_$K0xE9s=2-k0cHTn2<&g>B`F+WUf93OZ8QJuMG7p_JeyjS1-(a~~>HNEgvoNzZupA&FYfn8T^Yyo-#z~pl kOE!G18H{x^s(tWgZ6;V&+W&nHG@F|U2KoKVL(1&`0VBTT^8f$< literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151 b/external/boringssl/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151 new file mode 100644 index 0000000000000000000000000000000000000000..ef62d9ebff2c1082b503812a880da6b359b412db GIT binary patch literal 686 zcmXqLFlb=Xcx%wa(r~_sIb#8{h)9FsBw>Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#Nm?Ta?j6C&q-DA%u6;@HBbf# zG7HNX(84ZZm|f>l?1DPrXI@EaQC@0^!t&CRjQpa^l1haKMh0@?yoRQR21XW!7N%y# z7EwU1nSr5^nE@C?8DwJh76%WPb7D?rT7FSpW}=~(fe6T3lm!&r@u&d>4?U>k9U+eY zQmNohRmZdQ@cQPL=9MI7<|%|_rk2AakOvm1Aa_X^h=C)Jhd(zlGe<8S9JPAM`MCy> z2EuIY!1Qp=mWh##1I%D%WM_6_V3EADrAa*9-`F7f$4j}>b$(Z){6hH(e$MOJ&rq#$ zRMvchkD9~O&);?~nr-p8Au0QHOZE9Ti@1#1l=R=kUfx@c5&#*Cn;5eVni$g!QUUby BwB`T+ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537 b/external/boringssl/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537 new file mode 100644 index 0000000000000000000000000000000000000000..40ad5df160b227c3cdf0984790844acd16f805fc GIT binary patch literal 993 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%SHfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*M#o6CV|Ynr2GnG_i}?&^RuupGqE=qWWbDJWMqjkh%(TI z@eP>T# z0PzDKix`W@VY6pllXDpLwBrM#{jM(%Ob=Ln)qn@&Dq%*(|13-f3HNEgvrGho{Ql+r{~T2--FAP|?lzT^ozo<) zhzb^)6cpV)$n2%CHA}A1L1B^P!UO6ztSe=2MI5;7aPv>s3pcO#!b{g*HLR_;FhjE@ z`KHc?uiY1zw$)UpAl;4otEqcbLXq~xV&>HVV=Xva literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d b/external/boringssl/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d new file mode 100644 index 0000000000000000000000000000000000000000..f65e28b874f5c4634097fbd766eed3fd26921e2f GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eAQG%;{7H8C;@+&UwXZ1DGsxUy7O zUG#mM9E&G~+bbqs*|YG5&yN+(+n8VaDzbBQ+=|dov(((nTG2h%;sxvWth&M_&yFN4 z+wi{ONv8(?Jk@J&n?J8zHu3n3lTH$*B6HWyaGRv(f9hkq^Fgtx;kp6uJ9QhX!qg^Si7n=b;qeQeg^y?X<j9K4kep0xZBp#b#gyQXtP_ zY+z`hzd(0^cAI8KNlAf~zJ791j$V3dehDa2^^)^*K?244#o)w~oTvxn8Tf(pDzLa4 zxEeUKu>hG22G$0aY#iEbz_iKE#3-f zPDnPCFc1T~i-$jV82I)l(6`?e!ZK3{`!+E%M=u>56?)0}xdxF2!ffooNIhrE#K^`0 zW-v3dGdnS`NZ#4fB%bbXY!Ln9rQGQ{zpGJxp?n2D=k@Gos8%^DYrcU;&0*^AZ#x&w zws_o-l>NG;`uv+kTt;n5`fp+{@2$>Q+{Bn|(8QQ-APWp=SydKL^l)giF|x9e;+8t{M|Da^?DpM}YQ z!9X6wQ)U6CxCRlgyKFLI(tEyTY%TlRxNUcm)UK#TeFH_13I!G^0|}s3E?~&8FkY)< zVr4YoU}H;fH)i+-xH$O*L&fm z>#rKtR$Q2&S(AKI=fl_T7b?#L4=y?oZ}n2lQ1I)5Y4VxfOIw^pzHO}4Q=ED-FLvgh z6^zS$w{=)ubzjF@>k?2Hhfl1$m qJo`^`T6g`MDB_#H$1On9z>Z;3b?Vd11wu$U=KcKXz_3luR|Npl5RFFw literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645 b/external/boringssl/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645 new file mode 100644 index 0000000000000000000000000000000000000000..8e6697387d8c91b935e7d451285e8cb29833b17f GIT binary patch literal 941 zcmZuwT}V@57(U-Q-_DM6bIHd1N!`qrIcs~*#5DvV>tZf!DPiC&Y>u^a*gR*59Iq@BO~_=Xsv@eL)79 z+`R${mO-Jo9A&l2LzgY;eGwG$QH~-JNivB!+*dL1Y!FOznJd$sSu-J2t|K7GmO~j$ z^<&yX_8(;}P^lRPiyX1eD)NklWMNb{W((o+WrT=V9RQWZba27~LL8=jvJErdh;6{+>Sf@H`4Ga# zAq=fW8_0~ElcZFK$CFC%CGnm>uq)toN7K@lbBQ2XGoa1LXp)Z!(kNRRE=EUFf0$KZ z8@4|2EnUnek-K%MZ!q*aR~hfUxd28Dq6MK}m;?gsn$?8W{>j!uZ|SN0QpUFZ0ko`g zcTazxya&yXabcYA57*9yCq2-p`8#keRI7;$s$3W?j*~hB3{A%;jp}>@xEQbIWydYh z3{C=X$TpRSTvM)blRyderHqRKLX{M|WRI(^s6z6e6`>RY5i$S#^tI59fs;MA3p-ZW oDQ#w)S#yUP5G>s(SsV4A`CDaQntNwIy{mcu!!GPaGt<8 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a b/external/boringssl/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a new file mode 100644 index 0000000000000000000000000000000000000000..c8dbfdbad6de935b2b015502ede160afb3f167bc GIT binary patch literal 1044 zcmah|O-vI}5a#W^ZcAw?WSfG>PZ2ABrkyRJHlm5>p<)mriU~zSpsC$WOSdVDN-$=- zF-~iZb-`8#gFWD95bj2iFE9pD8t@H|G}D+FFmPF4eN$ zqF~L+0THMRq+}^YFbG6AjR(qy-VcMBDQ!!hPHvhJD$_lN9TkgUNVmG$LFP<56LT zvw@Yg`lL6R&x(^HngH2;kNqFFa#{4 zC)@jYoI;F2GiaozPnO_)U!N&ep>rKD{O4!=hnsyX{=UKT*w%wP>5}P#@9K^$^d35K z@9)Oq{C)3tc`W?v*7R~_-snyqaAhukelyKKR8SZc6oNX^y3T>s5e)4N(&_XxX_d7o zh^W6SFGVnPVgzzP3_CtFv093Mpm!#NHmn#+) z3IJTbo^GGp8Hh^-$!Iq@5D|h=X@bjEJkeBCu{~#9NVaszWMM8bFcI4ssT|v|^{r>^ z_G|<>+eZe5`@Wl~Snx(F&N<`B;RuF$E>ipn6T1JfCbm^Np#s?SH+& zKfn4r@#583%}am61&wNk9oIlLDK(O%VzfF%=@1wgCX_IdI{{Er8gMH#=Wjw@&Y$Iu lgfqnw-Ydzh`m>aC*GyVe7hW@17;vPTQjKJ(`3uSL{{VkX6V?C# literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934 b/external/boringssl/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934 new file mode 100644 index 0000000000000000000000000000000000000000..83452a8133921921ee629b9ecc7be5fcdaaf183e GIT binary patch literal 1839 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}-84NrPxeYkkm_u3E z446WL4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhUrCT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4q11qdnaqw_CC+1|P1S%*;~=%S>+gJuKfj0MahA`OO)BTMNqJO-UJ6-2@HOeoPui)pr zp8X8fDo16_H~6T1p89R4!=l+1j~kM*U$;Cz|7H=FQJa$fo7l^Ht1}iiF=iVyF{T^H z0RHyC8VjA3MCi7|*W(1!61nA+qsN=gc>^z{p}Gm-S`yL&pi8|ft%l|U3*F&Kax zWWWelpPZAKnpaY6h^#3;xwru04L%kz7Lmhd&$=e(FzRW?2S)o{Um%zsu==V256EG{ zjEw(Tm<$*UBEf)psQNEt`~b#eg% zgN4!XS|t-JqX7pSTY4i8FnSFPKx*V!G!4`ZR2L{OP=vb?i=PaEe#${g@vMy849rc8 zj0~w3=jJW+TOOI`~SLy+~p5K>zxc~c{od#`x<@0nI+4O@l51llAtNMo9V7Xf9 z{JV##(}&zK*xnCC-vtOsJG+`hOl@-Eae(*_s`ZuUV1v zwJwL8};O%)ufK lTUm@FR@M?<7(-(PQW!6KW7NWRz8WP~=CQIJ3ATwY001ae6?gyu literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab b/external/boringssl/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab new file mode 100644 index 0000000000000000000000000000000000000000..bcd14d28774c84b5d0dfaf7567f896aa40b04c8f GIT binary patch literal 12 TcmXqLFlb<6oWszjvB4Su78V1U literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c b/external/boringssl/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c new file mode 100644 index 0000000000000000000000000000000000000000..e6153bae55bbbb8af9391ca56ff303943373a83f GIT binary patch literal 1394 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&e2?c8#|hO)MY@ghAJU8ul#!ngBE)dp}DcU*ySX170>xtu~Lg z@4SqR+^h@+o`&28oNUaYENsF|p}~g227(|CmoS%metvpRs)A=;vZ1PhGDwhFSOzXw zl3J9PTB6`sT9T1plvz@#;BI6fC(dhVYG`0&VQ67$W^54!NzBYs2+K?@hr5dh*HCV}s})FXc|x`CX0j z3*{^LIj?6wL$%6LS@R7(Y7SFBf7`iew#DOyr0mx%)#u+V;xcMe(ti_sd2e;b;wHvy zgC@pw16iQevZ^c~2Xkn%F|x93jnA+qsN=gc>^z{p}Gm-S`yL&pi8|ft%mB7@p zvKuhM6({FprskCt8zSq-PcANi_<@f_j78+M*|V<6IgEPR@qy8P*B1z;2dutozyorX zFeBrC7A6A*19=cnnFSc=4I*B5*~Fyxe9PEc_O)@_?j)&QQH}bBiXa6FEK&v%K%HE` zkYHiFR>{Q5Xu!e7mfpw%OoavpASLoFng;3ystc4CD8ikH!#_D_$(6Z@k&z+Q;@rH2 ze#;{hd^Y~u`AR)t*Yo?55C6*N=`ynE2W1{QY5Z384Zp#1wbJ=_4`-PO2KoKV`~Nwr zR=Vx}rrm8SCp)J}ToDy4HYosS77bjvj*+S8_CaPZg{@g~jqv=Z=%BDja^Zm+)|Ili zA`V=3xcR5+g`3xVVb!JUuNu}?T$rI*lYCR>!`JQ?D$fKDE;l~Y{2NNVmGo$2aBTMW#+5{~}d%n&~ZZQM^GG30H literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4257efd87e9368cde94e8e321ebff4f3a623dd5c b/external/boringssl/fuzz/cert_corpus/4257efd87e9368cde94e8e321ebff4f3a623dd5c new file mode 100644 index 0000000000000000000000000000000000000000..14d6860eee35da739934e1ce38cefb492a30c8f2 GIT binary patch literal 1280 zcmcJPUr19?9LIOgJ-eH8bIQgvOP!giEw10H5c8*HCm=>fl zXTS@!l@_jz1FxU+xA|KAK|1vT=krc09$=BmJ<=`vdrAtCOLYU12sF#&^MV-56}FFG({joN@g2IioS zYdqu^4t+DZshZ;*j!jdVkPrjx;pnq42id>+#*8z-$Fz{=822$2)e6a<%6 zNf!WT>Uc>??e}<6F`>BgT~DB^GvIZH)6$0G_Cj$uE<}>j2v__f;Ss|lskPIU5eKn9 z@hx7Sj3c+}RR2)V>ug1|@Af>HRlPQZeh>^gs8eSRgytdJkGy3a+aE3S_s@L&7YOE~ z{tpOVD$rg)FkM8DXb7&%NFgEVqzInQz&mq#CNITPh(0EsSA3 z0wc>tC(JZh05*Sjr-)3=D%@SnXKD6G%YG}UX@fe_0!^^~3+VWT^4~*#?aSXmt}>a2 xJU`kD@`Bv0Ajd_>3uM2iWS8VtZcHyWn_9r61GSmPIg#f!c%wnTZV)}V>nD?-Pc8re literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619 b/external/boringssl/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619 new file mode 100644 index 0000000000000000000000000000000000000000..8c66eca18457aee89c13a4629e1438f4e4716c8b GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI5#z27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp~=xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcPxU|&TD94U;*L+c?MAiPRRBZ8;Ti-K|SorSR!$W7~%oyV=cJlIB#t5;OP`e?a?1 zVfK@sOpMG7jEfsT7&N{$kOu~%tTKy)fmnlx$Fq!|+Lty>z3zTPSwX5p2gU}&_I8I?gH&L&5V+g0xNy}7+G1_nHa@%L1q;L4J$7%M>VV{wK%`DC^@xQ zzbLgJzc{lbzo-&9Q2^66b7Lbz*+Zc`KW{OiHUqXzjU4Aca2!8gSeN$h(Az84^8Y`4 zIN^8A*@D=xe-BB^cf7acUHj=bhJ>5iP)ikTu zi)BPOJh$zBI`Mt8*=yOb{8P8~6emx3QeSPSblR5vZM;RvoX5-oehb&nc$fI8#a;*i D23A1$ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6 b/external/boringssl/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6 new file mode 100644 index 0000000000000000000000000000000000000000..b82296b17f01ed34d1c8ac13c9fe774eff0e8129 GIT binary patch literal 1017 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^$Q&F8BQW^qf=$&%9(qRRd*^AhV1NT(BgyC@-}{!LhU?BfluKq*CF5 zk%62zuc4`-fsuuwg{hgbMHG;0W?*P!W&j3J2ARlKX~L}H;Nfyk%=xt@zbG$L-B8Rx z1Y{LE4{t<%XqVrhx)E5h;*; zu?6xult30Y5QPLXUwL^sER3JG0|U8WzU}9oqWngY%X@lh z!kBf%OT25FlF7sE6AvXTWeD4UF$_OD@y5w5TfdY`Rw<@;eA#SwHbr0k)c)@ZJkrd! z)$QDFHSzyzbZlMsZ;wOoilxgYg-m#KvE-QC(sOo3{wzDwFFuM~EM0puLv+)J2}_n5 zh}p$w-DDTJ*v2}?;z4ohlPg|RHcx)KiA`DL%ID|jO}D$gdC7kF!JgC6${kj6eRWK~ zwm0kb&x-jPAn@sf?d+@TH6=G&)*EJ?-m}~+qHnXomCI zgB!b-hsqW6HR^APo%8VE`Q>`~8w?U+6PGh>-;@24cLzhosrkTE0LpH^3VP)~YA^Y) zjH&30vgv~g8A)3vW<~}^V6yQBhKxHT*{HIB(m97V8zU<#J2NnaLRm}(4F(NN8gCKF iN<^e#-vYx)!b}+p9Dx}bl#@Y;j0xQYSSIJtW&r@!0XaMX literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3 b/external/boringssl/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3 new file mode 100644 index 0000000000000000000000000000000000000000..fed229953baa3db2e40047da758cfd7fea4cd570 GIT binary patch literal 1328 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhV1NT(BgyC@-}{!LhU?BfluKq*CF5 zk%62zuc4`-fsuuwg{hgbMHG;0W?*P!W&j3J2ANo`;^5(OPR#kWW@Axarn;e+fe6Sd zb{QVu{L;LV#LPT}u*}qQxVw13?#hL@%Rmh5EFS*c#LOJMbg+Z}RM}IVx+u!AH$u z>gR7e7tOYK+>n(0x~2O3n?+nkZA$uYVlVHl&RE>Um~GI+m~J2ov|84niKW4yi8%ur z#)cW+YE&olKcys$h4F;3J8~GCn;IAyVT5r8o-oc#%Lj&WB0P+Fc=3gC4$x!NPC!I^ zj`RdXqURt9NP^xeNU=I&5ikWc85mGKY~?@+2jVSp15rrE;43dLhvkds?ZAxD#HfUv zI2lK%D`Pe?R@sbFtIlNBTgzqYSQtOXhfbg&Rz<54 zlyRzTv{V8es|5Ei8}$EKiZAd=&NJu>OlG4#kCuW2mFnaPe9}y%xAwHPMaW*%Gs}i` zc?sOQ+!D03KS2Z*A_saO=RhsT>O_p!*y)CQTu!;%a1Uj58`vc95@2P&ZBr&z)KC@#+7@JLkZ;T-{!*=-SpTIX=9n=+!#FlK+z^eqZaQFscF9^91 z?hJE=JUY|=G{7)o@KJ7ulMWom7}d!w+cewfFG}4r*nD+T#=+mt2VD3k*cgp-6?64p zcEt6CUlYRiiKSbA{%UdjT+N{ILB!4M%E0RLds`+{chtDWvQnXumC8<(mQTOq-}QvZ z5?^fo@h~|@wr}zHwmbIevdDmK?PsQx2c3JV{rl->|95JHaJ7+}OS_>57yV-FChctgroGWwK;oPi0Id0C3UMm@u_?! zH_=;)B=9lJEyU(mD%kiykQO~}3y1r4=2JNh&GLxI;`p_l#;0#Iynb+Sog~fFnvx-h zY1sM-rdRLuyS{ZJ>L%)BlDj_`YChP|)j?LG4!eeqMEbS3M%srXPh+5Yd}v35FZu^5 zFEMXcNvXaduZ)gHjzbY|@q~vFStg?`H8Zkg#%$FW=(TxPW`q+gBp?%l4qb94fQ+= z&cToqgcyo@5v(Q7o$%MfKext&jeW5y=loL!)uj^ofiihl>$WqgcXuT3C$FT1@c66F zy`(5elpo@h)oxZ@<{VgDRr0>;>qQ^#zHYlz6CvCZ-qW|@=B^Ld9jWh_>7O9kysJKC zeN6hXKi^0`EUlXtopHS;+O~Y&t{Z+J%h7A6b5)tW3({9d4`zfZ|1NMHU;BPy0Cu2`NL=Ub zJE)5JE{OB)K-x5ukQemnJ_SP;B zP_!?v*R83!zmxNdKvem0CG+{Q6B;y~!=T^*iFo05Nsy2w2Vxq|g(Nm1n2G}$6wYX8 zRJDAFV?zKyHvA6&@E-yoBS%WA3jX-AuWL&1gZ}=bnx16U z?q;Y2n}284ipIsqm9B_LIfxoA&n{?M^4jO(F7;q-_5w@5oxmzVL~f{26x{mJt)zmwSGGdQPf>XI`?Qs(~^{kXcyf z4Nwr~!Uh4bV}bV60_}MQv4>e`_cLTGSbgP}e{kB*HDM z0u@mRPE9T?N>y-9Eh@=O%S=uzNmXzxE%C@N$}FigkQ3)MFfuSTGBhwT0D>rSUPB85 z3pm%n3DrI^0}-I<=eUG<-Ba^Jib{)1K%UYwls1rr_(}*a?w*sMl$fL7>}b%$sD$hd zMpg#qCPsb+pg0#(6C)$TtuqqI27kYZD@%pdMc=o{v3OFry<*~(JqvI6{8-_`2104euMCbZYR=Q@!@K`SaRk6OYe0=_Fw) zGI#9^w@G^br#`kj9~7G!t{d>aQ@5cieC?-q@!6LcdUuNa5D_)KdBAOPb{MZjM^YnfvFOB@0jaJ-c$XdZpyq(0eD|T#B;@ej4N7qx&yF+3Zi+v(tS`EF~GX zPi3;4$j$f9Lhqt1>#T3ScKQ75vg>u^`V%Z4{W1#{w!9LjrhVIXg~(o`*AmPcK`ez& zR~y?twAjsV){-=*@|Bpum-qwPFAB4t{A6NgWMEv}_`#s@t${o+7-f}NBn-qFL_D5l z{M5d*Y3gC#V%)eqF3sS(xBE}+eplU`&Z|CpTtSLN#wX14Vcbq!oXTT4V z7G`Ap&%$cJ45Yy6LzW*TzyeIXYz9^!1@bJ$28IUu3v?G~w`pdSloVL$>n9iG=%uIT zmw+NwFF8LKBv7nh3{E`BiF!bufgeb(0*kwWtAR5c3y{fRU~OQ@#-Yu|$a;a5orzIQ z7igGLK{3#{^73+2vsrW zaYy8H29%5r&U*a+fZ4qywFs8u^HNK`E9`VEWhlwWXJ7#4_PyOvF~xt@-IO+xv{*ge zL}b;pORpEph;Vpr+x>Ln`)0G(vSInBZtW>fp75l;+D_@TE&JPei;_8ynFIV5uAlKP J@l%Vv5CEHRi5~y} literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c b/external/boringssl/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c new file mode 100644 index 0000000000000000000000000000000000000000..2d0a3841ea12455f62ef16b9d64f73e19824050d GIT binary patch literal 1081 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?+|g|l$*a5*RDWTxd8USYN!hPks?Wb!#AVc`r2i)N^4{u<#Z8Ra22G6V2C_h_WmQ=~4(8Bi zV`ODzX9ijYWic7(fTRUkfI-)U?z$#{%)F%h3S{?kgH-dgurM>RHyC8VjA3MCi7|*W z(1!61nA+qsN=gc>^z{p}Gm-S`yL&pi8|ft%l^`i*gey+Y$xO{FDK#0PzDK zix`W@VY6pllXDpLwBrM#{jM(%Ob=Ln)qn@&Dq%*(|13-f3KX&?y`wV z@A;Oowd`x-w%timyP_KP4HQ8N6j-DTB!D`(fFZ%cc&(C&mC=BMjV-;A2bc;C3_wcc zSu_pQ4OAB>FHnR#5r=Hz^>=_B_HnpK4+&v z+h6%ST}C$jpv*%jjo+%i;Wt>WRyzOg;VcuuAisZk|3637O1Ev=-KKJ~bDG2zQNd!9 zf}-08nY|RYX2~@=C@hj(c;JS0rR=SU1D73c{^@$*=Jj59>H4dNwG|g;Xx1d()cNqW z`-RFg!Gntq#J?0X6#TkintW#W(iUftZyRg%6sMldi=DY=1>uu-PiHfy2M#> ziwTwTO#jd0s~bL#mF-BdO>}`t--SH;Pjgy#{hKJ_o4>~`U{ZDJ)64}z@8?hV5pJ9* Y`CYn>MN!wfu0P8PE@&Et; literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b b/external/boringssl/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b new file mode 100644 index 0000000000000000000000000000000000000000..fbaa9603fe18cd1d7751254e59f276ffc19d79c1 GIT binary patch literal 1005 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P=Nd#B z2(z&R{d>-qiII&1%vj6J$j-?@p`GxWo{G8XbpP^di zsI2)0A2o-mpTF%~G~42FLsItZmg@6w7I7K1De1q7y}Y+NV{sE>wm}nPx`8avZdp|p zkkdJ|*%(<_*_nZML0L=&Iv{C5mLdb?CUoaD31sFaZ;;pM`~)iM_!f17-{( zBTI}ylz}#kZ@|zbUysHYtt80~j`fna*T>Z=AkAXf=9GX7^_GGH)}2l13yfT7+X z;&qozOnT3^jICu~8@KIFlG+v3sBfSMQlP*hWgr36$ps7v7RGCpOstFs9BgdqjXc2g zXkY+RBF~~}pl+bLKzV^8+=)2+lY^FUnVT3H8B#6I&0FZVJTk#&U{Xx z{X*rL;K4-);$Mmx3VvNMO+K@GX^XSSw~e)Wic?SK#m?Nbf^oU;whpVS?(2AKUE(ac z#efN#gMk5*teF~wN_nRL=ke7IpU28}B-kdpz@+a&p8cmet-JnB6!Fd9;}$TfI`wJh x0-^Wwr~3#u&XoKvUB{ylr<5lszh~tat4BPkW?M~l3ew%UznZ#7B@}621OO9pIY0ma literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf b/external/boringssl/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf new file mode 100644 index 0000000000000000000000000000000000000000..a798b2edea0f642460b234462dd8ef199c4eb2be GIT binary patch literal 1317 zcmZuxe@q*76uzvQ1euSpbbXyl*=zB;H@|=l6Zy zz4v*bQ1hUWpCl*}k)*DBn%aB40Df(!m}x0bF|*L z7FaG=Q^2x%d}7ERNP@Hbr5@-2meHzxUVex~aa~fNke1p`(0Si~q-+R0QVr4HZxw$2 zoM+DKY0vEa^poHP_1R?G1*T&UO7C!bU&eW`?`am6od%Db@|k3&v?hvyU*U8__?fY^2YVN zAEsAECm{ZJQMd{*j=kciv(>jt7YzUkHLTKLAw>f!XKG>Xiy95Vd)9AdHe{+8X+5hQ z-yD7O+NDD^=DnV~;nh3d;r#gZ52xZKvoD>@{pvn*U(I*Dk&9FdckWQ(NCP*PcY5ZV zZ36}0J~4Bp;p$&UZ$8}eD|_bsIexhR%h$?>{8zXBwsh=f$%6Uf*v!FOR^GgnI9Vj_ zj2=F6>`ar`xzja6+wTgVXuS3Oi}iEv_aFu_lDiEGtqQ8RB_%3UFhNOm%BdL=kNq=(T7)qFhb1{e(1oT%~D)z+%V)j|I6 uJyXyoJW-rGI`Q_FigJKhnTgS6RHVkj#}8=;3jP6%Dt(s# literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2 b/external/boringssl/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2 new file mode 100644 index 0000000000000000000000000000000000000000..dd35e586eb76745591d93e2db940f17d0cb6e9d1 GIT binary patch literal 320 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&buGN#m_X6APFHGYDu@2vEzu1wb=^Mr7}23FM1B8EwGJ#;Mij z(e|B}k&&Bqje(~jw*e;`)C`~#ni`lh48Tr^7X}(}ji3<>P$QT_S=fY`LW2#34FuVM z94=ul_x$|yoKywRyktXF17(mPv#`t?m|#h2QC@0^f@5h3(ONU|i?T~972J)0X21ff GK>z@PyYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#SIEosmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLHgKjc*O)fdMJ2%pzeR)*#~XEaRv4rAyWdb&5b!siF=74{16hy)J{B<+ zkpopTGI~3IuVzi*5v*NRo4VuF89xJlkhCx(<9`-b17;uvP9d`VAORL&vSKr^0x6JZ zF*YzX&|jdtK)X#dqokz3N?$*@C`T_nHNONDt$NA%xgddJ{bF$PNlw%Q@(lbydKFmQ z4O|VJ*;s%~1_NsYOEwN|Hel*xXJQo71({V0G_1V59M!O*)Z+ZoqU6+K{i4)@{Nl`# z{Gv+aWC2Xw%#Doq>HFBK)z;XO|VO`q0LvOEG%m4rI;e_8cXNwIx z4QeGWgf=hAI&CI6=Y>bw;@tWj!dKk?bw|Y%|5h=FRnsoLUMwTR;kj-1 v(~0k!&0fof<)6B>r#N}Sllp2qrPH?TZ{saW<~(K&@LRZk#=FE%E%rhH#mGWc literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc b/external/boringssl/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc new file mode 100644 index 0000000000000000000000000000000000000000..0164a8dca3295655bfdb84acbd6ed56738c8a2ef GIT binary patch literal 1111 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqT8u4TTK^K^!h2F8BQW^qf=$&%9(qRRd*^AhVDRT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Ve@o;cCC+1|P2-%(GGm%SLHEluL-{>BE;KVHh6uJgMZPfMM5!?z|>}%)F%h3W$S~Q}qnk@^iU?s`*)1n3>oc z3^HIQGAgpf7(^Lp!}x|wZSolkPAo|UrjMy5tdJA}N*)GA2Bt=a1}2~c z0ZJYg1{QFxffI_2M$nYNCCuxdnjcbBT3iB3i+YCA29h9qnT3U5;y}-kmeRpKf~9m} zY$;tBHKn5@bVEzx6FSf)M|h^<;K7#CdB7=M!96EGDKSUE*%6qylwgqo%%hB~49rc8 z{0u;0E~X|%MuuBwB$5sOei2ue3ag90ZOJ7BHj*eRq z`e~M$ds!>G=UTjA-JVrfxa8T9gk>AvH$3Uo;Gd^@?QQetwaX?RpK;Pj!c=7L+8J&o liJ5uuyf#VC|J28J=YwKX!*v7Rcj`7&g|Gee&L;a30|26aEvWzi literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/484c387f1936612f6e742f10775fa81593cb0c47 b/external/boringssl/fuzz/cert_corpus/484c387f1936612f6e742f10775fa81593cb0c47 new file mode 100644 index 0000000000000000000000000000000000000000..fe509f66331aaa90143487876d173c8865a9683a GIT binary patch literal 1508 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S&MN6lgC z=Wja~&9->lkd*zprTYAvMO;R0O8ReNFYm3+Slq;zZP3J+ZXgS^T2_?>*Cddcmy}|kz?YJL_LW+wIqgAAC7jEpQX22lpu zFunotamv&tpHWg$V5P5Lke!KSlfJvBqq~t_a#0DAv5alCB=paEkH|a zfeGmuBq1>i?S6)whFF1V$PXT|1`P%cOd4+unphfu+A{-|397a9u_`qnt>k9VX$DjdENDqe56UdS6w@H$b(c*{de1ke3;=18g4O^4 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90 b/external/boringssl/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90 new file mode 100644 index 0000000000000000000000000000000000000000..9f71dd3e5028c7d07130de6f31e36214fd19ecb7 GIT binary patch literal 1327 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhV1NT(BgyC@-}{!LhU?BfluKq*CF5 zk%62zuc4`-fsuuwg{hgbMHG;0W?*P!W&j3J2ANo`;^5(OPR#kWW@Axarn;e+fe6Sd zb{SsZ{L;LV#LPT}u*}qQxVw0e-DMyKb`}qRZenJRUOL#pddc~@29XBBZ0tZ^p0j0Q zWa9ucm>Jobofudo?`&xjPxm)Ai2m_X?sT2s)hNGEzJj0gdiFC^s~nXz-{7O>F!l4d zor`8$JZ?zJe%(@i{>>sTqc$b|H?f!ZR%a}3V$3#ZVoW!X1zIg@(8SVU(8Qbp4P(QM zZ#Alu`JYk}#=>~Q*c~~H%}ouAj4;AD15X%drsV^}I1wJkJov*H=rL+1Afi1-dIBQR zbC85BF#suO5ikWc85mGKY~?@+2jVSp15rrE;43dLhvkds?ZAxD#HfUvI2lm literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4a59656c14d04ce913197e47cde59133db0401c8 b/external/boringssl/fuzz/cert_corpus/4a59656c14d04ce913197e47cde59133db0401c8 new file mode 100644 index 0000000000..7e05e4638b --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/4a59656c14d04ce913197e47cde59133db0401c8 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|:‚%“;0 ¿÷œ¹æ†*+€¿0ÿ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/4a7220ebd75b74c4b91bbde748ea273342e7d306 b/external/boringssl/fuzz/cert_corpus/4a7220ebd75b74c4b91bbde748ea273342e7d306 new file mode 100644 index 0000000000000000000000000000000000000000..8bd54f11e5e1a0556fc1099a848763023d0dae71 GIT binary patch literal 24 fcmXqLFlcCCU}!Kf=s3Y(Aj8sNt<}`9mN^3eS%e2* literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd b/external/boringssl/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd new file mode 100644 index 0000000000000000000000000000000000000000..8ef0accb9eab95cb1cdaf68e02c9672afa07d011 GIT binary patch literal 705 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&e2?c8#|hO)MY@xIsXpLV#NKEno(+u0dE#j6lP(_p=1@MV^c{ z;AP{~YV&CO&dbQi&B|clX~=EB$;KSY!Y0fV8f++RAPC}c33IvE=cnhSDtP848>$*8 zg9Mp{W!&?jf+eX%c_k&Ksg4R6`9+x}l?v`g26E!OhNgxFMizz^re?+#Q9!PlfuWI^ z0T@IXWJ0WRK(&g4hs!xJCo?U-C@(Y7P|QFCXq6^A53g^2XI%0#lxSQn3Ew8 j1sJK2RMx=3&YWSu!~!#%k&z|FAWA_S#y4Qv-x ztu~Lg@4SqR+^h@+o`&28oNUaYENsF|p}~g227(|CmoS%metvpRs)A=;vZ1PhGDwhF zSmq5-5az@N0kCTkE@eP*Dp)Vby(OtdFem4wmV8&(=~&88l9A8A0P^lN1Be?NP#n1z G=t=-SXiYi* literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 b/external/boringssl/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 new file mode 100644 index 0000000000000000000000000000000000000000..b6595073fbb7fec2fd81bd496400a437708d9f95 GIT binary patch literal 1642 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf?MoV;X1RRd*^AhWOxRM0c8B(*3nwM41l!qCFh%-A9d$Tc%CG%_;)gD8VctX6UGa5*RDWTxd8>)fVIT%}7Y~1KVrGtBI@rZ}mv-kGL>dUQ zu>-w%&X$RhjRVYJW@Kk}VqlTHv!zKq-QU-3w2-=d8 z(o{zUSkM|YF{T^H0=+7$$^r@?4sA9@R#tXqpx2-*CIcNsptK+h(7Yy;&`8eDZ4$`L zOUkc+g%41~fLjx&nxBP*nTfr@AOmI$BO^CB=rwTJn>N3n0GWV-aH!Ic)Z#8YMgMstIR*IhO-={?^vww8Tu+_pPOYFAXFzJVf0 zfdY$^fdo(|7ceYX7_U__u`(KPu(72#@&MDlfdNQ~Jd37*x@S^G(bd z3z$Vj8Vn~1Gi5Ar1ZEMST8V&+Z#7K7Jfk|9|EU2#n}O;A&bzXXC$}uhau}J-;vc@UMKHE+dM@Ea^wD`Kq~W2F0OF&O9s`2!jzKEEg9k1i3lHNQmGAsX{!{ zT}s=nuDxh~;ri5%nK#b~1%lr^YlL{Agn6 zHc$e={HPq^aH+tLqR8b_F*f+;esogY{ObHGFFMH{_x|$wu0vZc&Uv`Qv=6&EH$g0U z`|=xld-}w~!t%A7$Q#1_%c|Ym0^cp!zUNL&&zcGH&B@(;wfA;yuRq>+az;#=a?`HH zS?}wz+JAq`^tGyCK}z>l-jdizM0$t}TKaD+|`^$-2or}qw>x;71r98<_GCsBkI^Nxu9*gX65Tw_K zMLZ#O->ZcmJ(xRt%>vdF5PRn&p@Qx=f(zZEF@6c+-o6$sEbr!;HpCOTNQWQtyI^Eh=y6vOg|sz2}`$$+;b4BV$S8(Ze7-4 zjBL6w+upK#)d5A9`N`V6Mc&7sT^ePGC0jR6R_^?;v$timQj)o^?Rx#4T4S$zKGS~r zkk_`MXH_Nmv2M<3Uj>~eDL#VFi&%IvKa^6K5P{6$@>f74Hv-OXQZvI8IVsHumyJk< zBp$>RqX)rE7fX3u6#L9(8nc0S8j(hTfh5Q@V=Boz%?O0S$lH!H9?&7JB6EnrRwjv5 zW_8kb#^a)`#Gw7evhcY~sf)GJF3o(JDjP~>WKy#f<#}o zU)VEe`^ydY9vs~IF?p?~u()@1<=IHuMjd+K_+rH$zI|7^pL;bHUN>3V{#>iAYrBlX15{0G|?%PlWN1+?>>$5G1VEKik}v-Ho@ccXg|Iw+`*` Ir6?!-3(_C^umAu6 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84 b/external/boringssl/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84 new file mode 100644 index 0000000000000000000000000000000000000000..cd94bb280f106d61f2a1d927b31a25fae2c75b81 GIT binary patch literal 1317 zcmZ`(eM}o=7{B-KdM*6`%GC~rz%l3;FxuzJhjohyjA;iMm2IL@oU=4Xd!uV>xhe#z zdc4hiAcv z6)mfEhC;r8z_kRuyamdzkz(&p8zmtU6eO-GD)~bZQ5xW!b|_wF;Olv?J9tNZL#@ND zs13l|8({UgK}?roGfHXn+GbBc>?bR>YR)%$jJxxP*seeLhgf*zw{5n7>1AfNFPd7fGUmebOa8OZ zEe@ZX>|Q_N9=1U#4&dnZkgsHFl{cZ$+yJRUpkWx_uwMCv063(Cu7nD(B+HVeX^8*R zPhib=-A+(4LWJPBbn=vItn-HZ+FOOaxDL=`;2{c;mCIvs8;Um{^H?AZnWUk^fy}vioShv`f}ryKM&n_r1e+!^!u}X ztpCdsl|$Yun}1t8e4~8ccwuyU-%T@bTudG-5f7g}*!=LbQL)F<&(|okQ!4A&^1Bvp zkKm0)1g=?#NMeuZ^+>`$gu`qDJJj2GsKfliY;%Akt-`joecdINmNhtq&|{HkpM$=w2(Rs==d zloDmipQKD%evrwU zTK3NkX<=ksF(1jf4mzDVFRDMjqHn8tLYd@$?lT!}z$3-UBjayxs;UHtR~Q&|R#ke< XsR&{oJ4&Gibcr3r>heP>f`Y#RoymPF literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 b/external/boringssl/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 new file mode 100644 index 0000000000000000000000000000000000000000..2111d2d44ea1ce9a6c631eb8a743275fde7dc754 GIT binary patch literal 1625 zcmXqLFlb=Xcx%wa(r~_sIb#8{h)9FsBw>Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a$Ps4Y;<}TcpPrMd;F*_fsA`}L zQo$@N;|>!nNiE7tEm3eREy>6)$}Fi=cwl58C(dhVYG`0&VQ67$W^559&TC|7W?*0d zCJdqsGO=03!okCpm6(&6mS2>YnP@0xAOfMj-@F0SJ+ zCnOt67>I%0#lxSQn3-?@p`GxWo{G8XbpP^dis4RJ*W(5v47A|2fcmUxJHS-NVYEDx>f7`ie zw#DOyr0mx%)#u+V;xcMe(ti_sd2e;b;wHvyVK^9=LY~oKvbzPG{W?oW$1#(*82C3#}VPR%sZ!pM!8NzbUysHYtt80~j`fna*T>Z=AkAZH0PGX7^_GGH)}2l13yfT7+X;&qozOnT3^jICu~ z8@KIFlG+v3sBfSMQlP*hWgr36$ps7w7RGCpOstFs9BgdqjXc0CZeRdXBF~~}pl+bL zKzV^8$ccEolY>?iFgGzWGNf9Zo43$!d1Qjm#(z6ssR!(OeqZw8U->*;MmGJR%tI$l z-m1RgH(0J#I{)tBEEB;XzkhlEKS$L{x82{gyG`X}=QN2cqJqUH1qO&h37Dneg%VT7 z0!LtZ#K=^1`yjKI!qzOgMkbDcjBhne22F|%3X3Ec9=Ks$DSIp8z-5PME_~!4) z3~+l|Jt=j8(EIt*eS{llN`9BFgP#2gcfg;?(Do_!H;MC;OBArwP=hUK-%(Tqp#1eyobT{s=rtVRoI9ZWU XqSTT^170>xEe4ttrXjZh0MwNa8vpJSEU?!YGL&wmNFqs+`p(e&MG{1^dZh3ZTMxLN&eLZWZjR5?*X=b7 zO6zOqYDFY{$su8^6L`%;8iQbra0Yc1^i1}GNv^7u`HED0xPDryr}OGlhf@nCg2>lu zppDIkJeul8G(&bDXBjBQ4{IPdu?86!gC`aXwg+sHsGqHdDhxz1<{8t**s3DC^50kEI8e)yV=#` z_Tonuuud1qmlwG8hKuw@!$Dt!I~z+xIUj2QGal4yozZkOHu!Ta!$oZ;xxjfzi9=Wx zgHfJpcF(0?!NrI&7WVtNh&?FJ*6xq>Lk}>t4h#EoA4$-9`Gz8N)Bz3J_U^t|5tE-`M{l@43Vq=(mxo`?jvAb)osQYl zZ=Mc^Zi_@1L?Q@QOl_@3Qp5TNn$T)>6sF4FkrGm%z=ku=y)7?ltI*oN(!v>|pOLKLYJAfzZk5a<-t zc%eag!IG)U5YNY39FBOHQ+dYWX>0X3?fwM6Tnt36*dO5nQGS3`t=OVON}M2lW>3Mk1gxnIFX8G}gBK&1p;g>d_V`N(_P zvi-??=)t*f$%l{o${u->4%i_T*iadiE{h literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90 b/external/boringssl/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90 new file mode 100644 index 0000000000000000000000000000000000000000..d6d1eed8198b4f55da84f2ac219faaf62ad15350 GIT binary patch literal 1624 zcmXqLFlb=Xcx%wa(r~_sIb#8{h)9FsBw>Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a$Ps4Y;&RW=PtQqJ@XSj#R5efr zsbChCfeV(T7UiXuC^(juWaJlRmQ*S{Ffx!6=QT7nG%&I-v@kU@wulnvH8M0aFfafU z22lo?*sNmV;Ni+j%*jm4FUreIG!!!s0a?Y)!|R)0npcvTnWqqznOY8Y7Yh#;SN?Ih zyCe+6!0zJV&rQtC(Mt!rST8w0*C5hBn2jCi&2zR)jBFfW1~Vf&vl9c0~PE$XB+qr1A#p8yg z?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO>!pmoO z1uYj3vf~j!n?tRj1^L^7kiQL@7}E`8fw3y9$^uFY9NKJ*tgP(Jz*vN`m<)74(t<3& zRN2IzisZVa{M;si%)F%h3go1~4N}d|!otkN-e8acGlr3oCB`7i%0L??V8GNSpHWg$ zV5P5Lke!KSfWEt@qq~t_a#0DAVn(>)0>Siv)mII8K+Y0oWc<&->%Os|Z1&+Yt zh>@x2_CaPZg{@g~jZ7Q?8Q*G{44M=j6c$M?JaEIhQubEFfy)jz|8%`@^Lj6=x^(?j z!`g}qGc;?GZ|Z#b+WkW1nc%@i2jX9f847+~Fik$QdufZa$hVEPdWus|=Ect3vx0HC z@3s!BtM2P~YhB_jxy6J^d8Ys8@zo8V$I5mj*e1Hbr0+tW{iivtyZ%iS@y*|p8Q}J` zdQ$2Fq4)Er`v^DAl>9DT$1|B<>!|@h8|VJ-b9O${(9$%pWH4aVh%?9|F@+)*O~A0I z1(wOrAZ0SM(C%l*k-!Qpj{V?e2BO#P2HnFak3(zNc-Yj UgGDS2sPR$^jTk0oSbQ)60A$tP=Kufz literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c b/external/boringssl/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c new file mode 100644 index 0000000000000000000000000000000000000000..2f28f2fc2c2064cecbc95fe65273a0d223ac0f6f GIT binary patch literal 976 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|Oj_KA z0tS3+%)%xtT|jengAK(D zL_k(>3G=$A=7$uO7MCb^<|XSHN*hRm#F>SK;NtE%`ALa63eJuOO^iy&eqm%~U~XdM zX8?+GX)-l2GBVscBav+I_lvl)R9Ic~eVZJMCxzQ9CSKXI@P^Ni70%n3U-~Mtb9CH_ z&`-0}+{;?gJ=fv|>-Ma=!X?j+BrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8 zr00L?W4rS~v8my@0q;9?8>+(BetH+5eTkuWr^pWxQPZ0T+!j|CotU`)WT^Jp3)Ai9 zsHL2_f38`w@RZ-PD_5&mN}dh9cjC<@9gE@|8V!K@L)QuuVWvF$^P z-R#z8ElG1KUx@`6e2G7x{h~1Y$xkL`Mh3>kjUNme-zLZdLsC|mMZ!R=LB!)(#!u}_ zo2FiOzoD!k;BP!*!u%@+vLFR~EMhDo2dZXd^mhJU&6>g^Si7n=b;qeQeg^y?X<j1PC{k*K>{qm#KmS{1>(!I7#kQG=r7P+pxvgKQBqQ1rLUh{l%toPnqLBn zSH0x?T#!Jqela-xBq!&vNH*z&_W@7=e84RoqEZI1;*??)4 zorzIQ7i4BJ(9rVoa#TZ$Qj7CTi;`3Ii&6{ni!)2|iz*E?P}4edb0b69L!mrBZ!w`Z z1GY^aCm0N5SQ_?!Z(wNH(8SVU(8QcEXD1}9XmS`DWLSUuKW9UmMops@$N3K&$B!4* zrCB$;J7fUUXsy-s_KLOq{|_Hd_+4|h*s#-}R^mcv^P;TNW`c8Gc%&`Pt=}Ph#ruU4JR duhrDB_N{@P(rH`vxA7Gva~?DE2KX&p4*(omTAcs@ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a b/external/boringssl/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a new file mode 100644 index 0000000000..202ee12c17 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a @@ -0,0 +1 @@ +0€0€”€1’h A0‚ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0 b/external/boringssl/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0 new file mode 100644 index 0000000000000000000000000000000000000000..47c240d4c3a22144d3eb7e15d5f3202258bef677 GIT binary patch literal 1059 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFp1Y@Awc9&O)w85y|^8X8!c3^d*vG_f=o zG%;r|i-)BTMNqJO-UJ6-2@HOeoPui)prp8X8fDo16_H~6SIO#S?A=c3tG7LOZ} zvR}7UpMSH6%cxCB|4r=Wz11KGFhK%V02r_fpdkwkWUP_GixerW1OnYBRUrp!pyz>1 zPs0-Bq?itgQX|YL&BKgROLG#V6q0!G$7m)vMn9v+D8Z=ASlq;zZP3J+ZXgScZCOnaNu53;)?48*|h;^EIt%*@eC2fJ7=IX~AR(m)BTMNqJO-UJ6-2@HOeoPui)prp8X8fDo16_ zH~6SIO#S?A=c3sbj~kM*U$<1Bf3t|os7*=#P3+~p)ftPM7_$wU7}E`8fp*KPvVdI7 zq0Pp~%F52n2xl=F=zydJS%6{Jgzmg1fy}(5{0d|TbAwd#v#>BTu{RiGz>HyJWQj3| zGSG(c4Vc>GGfGMdtn~E@vNMtN>$`h8x*O>w7nL9>W`rwF&dE$Qz)TOC7zu(EIYA)D z65#}qNOpqw#=?fMDx3v1LFAPb8zOr&Ke@O767+m5Vk{zu&7O5l&SBKkjt`9XyS_j$ zJz(`!10GOd3NtePXJIm6FpvlFlv#j@r9s5&E}NM2o^Kgj%f2>l+npq}E2>f7KoO)s zfknzd0;rP<7?muH*D9G<84Wnt*wPz$fVs!O0Hj2oMbkjtKy`ug0!4Vp;)sSEq-@5@ z$j!jq#K_2yYH@DfLcisa2|gSD?R=#kuEL5#DU8WH~)0KaPxXEymb9l!`g}qGc;?GZ|Z#b+WkW1nc%@i2jX9f847+~ zFik$QdufZa$hVEPdWus|=Ect3vx0HC@3s!BtM2P~YhB_jxy6J^d8Ys8@zo8-l6Ig; bhaFLvU`;zPoyn-B5HQn#Lx_#p8kE-oNsd;& literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833 b/external/boringssl/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833 new file mode 100644 index 0000000000000000000000000000000000000000..cb767023a2cbc85bf1bdb696987aa45326f5ddd5 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2u@fyQ(&I$Eh=Z2K*ptVMfOPEUX61Knk2bWcfh?EWkv?W?%(UAkSiK zU}&JfKzD(5n`TByNr9EVesWQcUV3VN2`EzalJj#x0>%2p;KY-hs0ZX3__4XWh8i%l zD99Q(v$2HADliyW8(6Y&XtM#+COZ?Om@deyVxVE=<>jb`6{QyEmlh?b7V8(K7UUOa zmgE;z8t`hheQ)z%bvWG%>e%@k2Z3b+c8ad8?;5dG~urBT0p|@A8<^O;9 zaKi7Jv&DuT2DK6wLYo(5oi-Dk^TH!-ac=z%;VbU{x}#!>|E#+yZ6s;2db)|os%ciQ z7t4rncy8PMbmIGFv)8g=`KNB}DNdg7q`ult>9j5T+jxtTIggnG{1&dC@hRl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#NiU=a?j6C&q-DA%u6;@HBbf# zG7HPV1xr$k@={9_97{_w@{2M{Dit0W8OVwA8k!m!7+Dxvn3@?|L;<;G28Kpv24E0n zkcrhQ4jwM&#GK5u{Gz&Bn;e%FYb53(8_L&;dycvH-)b3B`H9c&P=(%QHy4 zFbnN|h8!iVz$o#9htqLTln5B`fqcm&%EV0r*0h=7c5HB3NNO zC^$PBG%+e6dzg`xfw_s1p8+V&#ni;e$Z+e7M6$tOEDlwj%>UGYpN(_>_c=Q?HMBGh O?7oOAONG@%-v1S%*;~=%S!el8Z_V5Q-V$ij#9PQ}arS4Uu)^Cl?n$ z{J_T|#v*dq>{-|397a9u_`qnt>k9H_5jif|_uWMcJC4q9?$ZenC)NVPaOZ=v7v$ONB_|8~Ao57_nmzU0Hd z@_D+9Z2Cc&hfW&5Rei&6uw1Ql{@ue_CW1kJ|MLESj;fVzyT567o65<~X%bgN1&d7z zif$id_EOlIC8yr#ps+}C;Q@mNgN6kR3=IYb9VZwJWLO&Zf8Wr=(qPcUoH1u7Bp+#V z7-m?1t5KcIuhrDB)_|9pEyLi3b*1dBhy#}$ZvN?d;pX*Tc}`t--SH;Pjgy#{hKJ_o4>~`U=n9_>eI{xLht8K_YrQK pDfwNxjz=R-DNj&-&&n@Wk9bnewwme`q`Pr{HFb|lDAK-I3;-4eM3Mji literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23 b/external/boringssl/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23 new file mode 100644 index 0000000000000000000000000000000000000000..6aabed0427bfc6392f77d96b20c3b98e1c069222 GIT binary patch literal 1018 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%gt|;?knz{9^s0)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgzng#$a CbxuYA literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/54faf9d362f22ac220377a9d478731301876830d b/external/boringssl/fuzz/cert_corpus/54faf9d362f22ac220377a9d478731301876830d new file mode 100644 index 0000000000000000000000000000000000000000..b15aaee943ef988bf29c6ac4357cc645244df6cd GIT binary patch literal 1222 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQWbe~j(oV;X1RRd*^AhWOxNH8Z=!85NUwJ0yOM8UDNBqP5l zv!qhN-N-;roY&CQ(7?#T(8AQr*dhwZH8U_YGBW^!D1%I_R&nrfIVa|1rsWsqWhNSm z8HfO_y1>rE>ziNtbL0N~-xb0#Q_JD*;sLu0?1W@P2?H^(yLk9>6Ek!4(!q|?OU}z3;CZx(SGwJGVpiM_nHI%9DYW41vPW4eJX&}vy# z7LbEEwAmP0S=pI^RzX=z200*UK^9=pHGy4cjc{F)KxST2eg(37xk0M=Sy-5v*c%Ko zV8$>qvcwpuM;U0t1PqwkwQ<|-B&l6djrsdn@9=Wrv%8x?WhjdA%22y8fzRZN-Hdnl;Hcbv}IUexdSA@Zh2Y@m4Rz z3f0#hPTgj-kzDxwganp|3xs^FYjRFavNX`P%{l8PumK&6L) Tk%6g^p@9jgya1IR76ujoeUx%G literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 b/external/boringssl/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 new file mode 100644 index 0000000000000000000000000000000000000000..b5badb0c02c60db9cb65162a343e8bbfd7cb3422 GIT binary patch literal 1631 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F85T0^!)rB&b(wpRRd*^AhWQHdwza;PO5@uUP)?EUTTSgV`)i7 zeoH z%F9eN6f+P3S;fx7>ziMiSCW{Srx2EzS`KqpJ`a~W7bC<8$%YaJVqkai@aHCG=I8;P z3zX4I&d)W7G!SNE2YU0IEfXUf2bjUk$j-?@p`GxWo z{G8XbpP^disI2)0pJfhHKY!b~Xtu@UhNSG*E!F4WEaEb1Q__DEdwFkl#^NT%Y=b7o zbOTwS)v~HAAO~}3voW%=vNHp%g0h$lbU@OAEWn^^LU&!0KxST2eg(37xk0M=Sy-5v z*c%KoV8$>qvcwof8EC`!225@886_nJR{Ht{*_lZC_1!%k-Hr5;i%O6bGeQ(!*Vj+Z z$xO{FDK#0PzDKix`W@VY6pllXDpLwBrM#{jM(%Ob=Ln)qn@&Dq%*(|13-f z3KX&?y`wV@A;Oowd`x-w%timyP_KP4HQ8N6j-DTB!D`(fFZ%cc&(C& zmC=BMjV-;A2bc;C3_wccSu_pQ4OAB>FHj`ppB%L0%G|`r$dGDr&Y+2Y zlp$>Y#W4Kr#2Y8KZ2eL$S*4iX@ny5!*%W==Q~SRw@JKV?R=0Dz)x`g=(XrKG-JXBF zE0!*s6f)t_#gb!kOV8OE`LpayzxXI}v2^Xt4AD&=CM;QMAZ8bzb(3A>VjJrmiwDK2 zPp)`P**y8_CN^b}E1#dAH{I^~<|X^x2YXIOD|cAQ_0=)`+TN_!KP%>IfWW5@wzIFU z*Oc6BS#Owmde3sRkoE-!v_daW47Z!!JmayuRciMOqZ!U;4{q#U9x7MN*QmcGcFx0t z=a=i{Z!k!ROI#=05RK6tY>6D%w3|2_wr%}oS@{Ql)3W%mC7oI>QY literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/55ff515a21332c377e8682bb0f05d4a36595cb18 b/external/boringssl/fuzz/cert_corpus/55ff515a21332c377e8682bb0f05d4a36595cb18 new file mode 100644 index 0000000000000000000000000000000000000000..5e416abfd011fdd8f22eb67dc6eb98966bf14a4e GIT binary patch literal 2117 zcmaKteNP7uO^W@@hg!qzPCwX`-~ z6RXWcOAXL!4S0W~3!UR5{!0deBTbfEwq&?o zUoKlrQ6wR7fN}6OI8H5s37HTz7yzO&#Avq{CaP401*TyyQ0Zn(*QsL+R{OAId??vq zHZc~vjUN64Yp@j#9KxTHQ?k!Bo>$*C<1ta$bF=i{x+VE(+dDwS$&%vuU5WqQ7>vplHs{GP_jajmPoYB{Y?$7$t8${?iI2DU#WvBecy zzdJaKAf$)UQI?8HlQT5`j^HpH}g%gQ8K-|q65(CSvpGw(EQ!?&jHdnK_$_mN-uWt)=IB4H}F zri|${xdVDOu0#Dqy-f6W2t(}$2fDh*a@1qbz?sN^M$i2Q;>gt)=pP*0k>HR1LqrI{ z6Gg?Qyqpp`8hH*ye5K>=MU?4`q1ehOlNhVrlxH&J*qQsJ;4lGdh*#4P$AN*vgch_z zOPKLsy#XSidVV^F^&b8yYq8Ca7-Wc{gFwNRCZz#rb0DrWv$;8DWzuvsrDKPm1?OSN z3t|k#eF)AJ=Z*&&;IHeW!bZ=p$U6V1S$nZ)e@SF})21^ix3(qiBQK?f3WTqmds>y3 z5P6VSvU!Ub-1Q=Mqs>b{f?UCH8FFJ z{`PXxA$j$J=(L_y(T?XA?6`I{yWkY|dV}ni?4kIxEy?v|)+1HTtr<~YwXK_4JO0_@ z=TEFq6dl!j+B?cVP<)l~;4N zI+*uvU+Pp=EC}8?Y0R5T5`OwalP*nYUpzkQyD8gb2i2DY$%uJWQRnv9DHpVj0?o?Y z+R|U;a6P*vs;j8r;%$P&F}&W{3(oEbW_zZ`csuIUp6YLPXTp>t=fu{$wXuB|DO#Sd zF}}X)&+WWtMUwIl%b8D(9@nGs93%w~NCXV8NrJ^3IuO)wJ|uDpAyh2TpmImMqbef@ zKsG=C%MaCtN*$cE6meEISRD_9vDTWmEjHkFkrWNjup zYb_n_EHovg(}_KIA;6-4QXWtV{5?+L$zI{%!$lQ&S3m1+pB!?xxA%ztbdq*g1C$50 zWvr-MdQ9Vqm>3C?+OC;-^~+xTMB1+FU!A$grnnhYA&OW$)*=aM`rvxvPa;OMH-1uK zezGrk-Tyxg145W~=cBVhYK3J>eTWhcVnM~7f+F5foCjorE>ziNtbL0N~`xL@5Q_JD*;sLu0?1W@P2?H^(yLk9>6Ek!4(!q|?OU}z3;CZx(SGwJGVpiM_nHI%9DYW41vPW4eJX&}vy# z7LbEEwAmP0S=pI^RzX=z1|V5M7GTIVfgNX!a9oo>W?oW$1+sIwL8|##SeTjE8w@gF zrZ6(H#2BbY8EC@<44B&FGfGMdtn~E@vNMqk(0BKAbT`sVE-FD%%m`PUoRgWFS5j;U z)v?Z?!JvUj;Qt(v4Q(3M4Z!fy&rdEcfcU77MT|w{u-UV&$vKRA+VO$We%BWWrU$IP zYQO_>q%b4ne-UGYpUpsZf${=HxEFDRM-C#nbAr=5a}y&YL#oBO zc?%H*O^;ZpRD=y5?tVzD9^Wkgv3zcVr2NxZPw|XgN zDEM{3H2KW#r7g}P-!|6jDNa3^7dvy$3dZHW+d8bSy07D{b&0d&76UqhgMk6;lm?+v zp6UO2e09U;v9cWrwuzpzQ&U5$z@+a&p8cmet-JnB6!Fd9;})Q4V8<}2I`wJh0-^Ww zrvpP27@Ah#Fk%3v34;b8*~DB64CQAKPcaMaeufA_MqnyuFz`do#sUU>z=#Hx80@Zv zrI~4o6^6RNL3vN)Ax5VPIrnYGi0& P0xBp##fF7}g^?iuGj(po literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b b/external/boringssl/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b new file mode 100644 index 0000000000..cfc78b45c8 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b @@ -0,0 +1 @@ +ÿ÷Ñ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/56ef359b39b367bc94f66501729907dfd8fb8425 b/external/boringssl/fuzz/cert_corpus/56ef359b39b367bc94f66501729907dfd8fb8425 new file mode 100644 index 0000000000000000000000000000000000000000..7e67019fbb5fa6b9db9225dedcbaf70811675b2f GIT binary patch literal 64 zcmXqLFlb=Xcx%wa(qPb}oUwp;ib#XuBw?nE1&+*2jEqc89EKU+YM2a~m{ce8KQ-WG UW7z+F&dz6TS{zyp`wbcl0E7w^3;+NC literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 b/external/boringssl/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 new file mode 100644 index 0000000000000000000000000000000000000000..55d28feeb9d6b5e8309ca5f6b91fafffd6a3fc0d GIT binary patch literal 1934 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?l=1mRY3@NhXN=47Vj7v*Ip8j2Z+ zfUIKY;q}cg%_~XF%u@)BE;KVHh6uJgMZ)B z&Bn;e%FYb53d&+K&;dycvH*jw3Eg!~0-1S9`4!0S#c*-omKyMK7 zy2~aez2{rT*0QgS+jb{O?TTvDH&6sAP+*ZVkO1oB0)_+&ru9cE3=0 zCU|hsf%unVhJs%gOq0*-UfSX;@@-?S0nPJTNl9s{qXNl!%>gxAW6Nurc=H;(3?L(~ zu@KH{Y6F(nRIuhX1&Z=os(x~24ls8j@|vFF)RTF!Gxw}uT<*KA!|JO0I^J5BI7@CZ zp;Dgd|9O0M!{@QG9SOFHE->l4kZ1pCPV26J6GeRU_qYX2s!n~Hxj^Xs{OLZzjWZ>` zOV{ye#3|(o${REoG%#trHE3dKC}?8NSimeI(qK4Am?>j{Be19kmGy=%zSS_Kf(k-? z^0T=iQZ}!`na%A;%;uR`i!CCvxgu4vIVk)VFfcS27<8OqFpyzs*#CV4Ff4(2IAhLE wNNuUfVVGh4twwb+zgAPjS_58YwhRNDrNalE@5|aP` literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5 b/external/boringssl/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5 new file mode 100644 index 0000000000000000000000000000000000000000..dd27b81f92ffd06a6ed80278bc43183f71310375 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9*ghtowf^~aV zUEz{vM-rB8c;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKL< zx(!v~Yd^h<&%VUayHn(ch^Xn!18$3}i%v}3e==12?1kxebJSAK+&|YWS$N9t*_Er+ zD<#i{-aGN;Qk+Hb(-{9A-G2efW`EM2o$gy=Dao*XDwE|zZoYpOdKYC`XMOXv%jaj8 zU9Th8pJ4gumszl|<&`)!?c261MD`lJmSENhVkvyO+SvA?#cp=9mZUkAufz<##2?Up zQJBrh%*62Xi9uuI2gb#34dj8rD67mOVIbBZ;_)owr}m{yQ?I+nRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj z)Pnrt%#!?~O5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZtX?mc z5#jLMw)^SC_swRnWyA7M-P%)}JmE=wwVl#wTlTl{7A12YGY9xBTtDMo;-?mSApioD BK<5Ae literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 b/external/boringssl/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 new file mode 100644 index 0000000000000000000000000000000000000000..c7c90d207373e87299ab332fed124b508902056d GIT binary patch literal 1055 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWQ{8<=28YEfQliGpKkNk)EAW=W-j zyODvMIIp3pp@ETwp@pfLu|*V+Yi3|*WM%*cQ3jbWO}a!$<2Ov^9I%S<#BGY|n; z#m>X)n_rq&l9-vN5SE!*4tEz1vb!V<#K7+2;m=LX%+X5+J5Db-Ki44AK$wjk=*@Gs zOpJ3lzzk+ac4j9A7RftXn#9xnjSZrIyp%g#=XW*AFO;v~=e(Z%4Am+}Wz9GEs5wmi z{B7r=*%pr*lCod7RG)vdh|8!=N&ijk<-OGzi<=m;4VoC!4P=2<%c`<~9L%B3#>mRb z&ddmBF&XH9qy<@kLDz)tx+a0lyrldJWcPA|RP(d2Ff*|?7-T?=$zfz4w#%q;Ktc(U6Y;5U`Jit_FU;t7g&!TCd zZlJnAd4VF_i8%a|gO*&Gn-~}wQZ3HSTj;kuGQnr#zn!nt19m;XFZuAVe4Z{Nn|@H{ zp_9gMRp0O%ELSU?fA?^fiC~c5zr6pSqiUtw?r+-NrgE}#n#2`R!D5qwqT2_Vy%e@) z$u&ACERtM!;D&Xj?5&6cmmO~Y>3ZSj^9CY%*%{SO&o?9-)fi)o0wE5^FIZK5X1iOb9O#! z)8f!-*nhyFp^nEuBTgw#P=3$KFIIDQwrM=#Nj2MQs#B2e#{JdW)IBPpNc$oHIeShp literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5c7389e097519d3d2c974b7d082344c6fdb9e74b b/external/boringssl/fuzz/cert_corpus/5c7389e097519d3d2c974b7d082344c6fdb9e74b new file mode 100644 index 0000000000000000000000000000000000000000..443034d206a8178f8770cc1976894dbc9af3c0f4 GIT binary patch literal 992 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%SHfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*M#o6CV|Ynr2GnG_i}?&^RuupGqE=qWWbDJWMqjkh%(TI z@eP>Tjs=nbjSguw&|L)-|6Tu+Ae|i5uN7YKV-QTpkP32_gG>I#sg2g5U zMYj(!dns(ql52EOSR}ddzzyq4*;^3@E<4=()Ahp5>%H*O^;ZpRD=y5?tVzD9^Wkgv z3zcVr2NxZPe<@}t_;tZF`ONO6EzTm}HrDDXPCc0yJ9Ezp#^t`-I;^g`uj8$CiL>Mu z6DsAI{-4KJH+&u|+mT?K=mL|z3widR=CtnmH&Mhle~(+hr0UeCnG1y8&!6ri+&EM6 pyL26oMx0Wfp!}YdU#uSSq?&Ct)hS4KI5hwO literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5ccb2368d4f51967b4d79b062103604a0e73c6ab b/external/boringssl/fuzz/cert_corpus/5ccb2368d4f51967b4d79b062103604a0e73c6ab new file mode 100644 index 0000000000000000000000000000000000000000..39ac6cb471c176eeb4f8323207472938ce8a18cc GIT binary patch literal 64 zcmV-G0Kfk*fG~gpDD5zU1b{Gt18ATF6cm78k`n@Gpg{uy0RaL62r=dMd;&0n0wt3V Wkpn*x_tw9rz!NI`LV9>;z zv4B}bq#=HiFjK|?N1$~e`wX9ct6>7#uR59kDbP-i{om*8eAcGLVZs10wIsDDFSSI$ zv9u&3zbLb$QsIG-ft)z6p{b#Pk%gg!shP1w6p(9XU~On*W&j3J2ANnL%fZ9toS5?~ zEx#x)Q{7O^Km_Dib{<~e{L;LV#LPT}u*}qQxX*ZyeI{Wb2KE^be{N!Cj$S(0&w9!E zxdxF2!ffoofI4T(#K^`0W-v3dGdnS`NZ#4fB%bbXY!Ln9rQGQ{zpGJxp?n2D=k@Go zs8%^DYrerp&0*^2Z#x&wws_o-l>NG;`uv+kTt;n5`fp+{@2$>Q+{Bn|(8QQ-APclw zR+RmEiho8K_Zq}X!kSZI8_41sUJL; zj)US|rNiJb_*TPZ*O#}7+8i!a6npmJw$Hd4CjINAt^ViPVSp$qNE1+?npd`Yw z|35I5WTqun80s2mgN)!7Rsk9T5>W_FO)f1;Rd7x%D#=XCOinC;rHe%{bAd_15G6?j zWI&QcDlFC+N-9BdZeV0!YGi0&0*Yi%oLd-Jz_|uaaKC`lCp31sgn8Xl^FxYCi%UQ$ zRL@Y_KoaCYW?>OJ7BHj*eRq`e~M$ds!>G=UTjA z-JVrfxa8T9gk>AvH$3Uo;Gd^@?QQetwaX?RpK;Pj!c=7L+8J(>^xFJSeQb9=C^j`* zH{gAzZbMc0+E4G|voA69?iBeUB5Hc`fZO8gq7xJMpA6MLdttiW9JQ1)_s=y;7M}8Z zcI9gIO3AaK_fEXI6lW3qG{(P2_g{dr*`Ks$r~8&zN-}Jp%49i_o9~~6-bGo~S>Jr^ z^7+|i*XzjjCs;oEWfm-Kc_mIw3m7%PoU?(`K>N1s3X#1=uO*l@f>;Wlt~R!PXtA5! ztR-nqrKy;~m-qwPFAB4t{A6NgWMEv}_`#s@t${o!6)Lj;GfIPq$Fq!|+Lty>z3zTP zSwXx R_*qz(nb?7aNd_d%0{};3by)xa literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 b/external/boringssl/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 new file mode 100644 index 0000000000000000000000000000000000000000..88bebfb591674c0351beb33464bd70b494e71d6a GIT binary patch literal 1492 zcmZ{kdrVVT9LIYfy{&yvOFNzeicsaD?eCVy3Uisrq=NuM8BWVoN^@y1)Z0>SHwZ#X z;~F2!5@qVl7#22%%aTo(i2-rwbbpX7&P8GBX2>?}aD%W+0hdhNy%ktZw)@vP=l;(3 ze16|^en0Sn7fqW2AMOQTiamh6t@e@!Rj55sfPoKd10Na;V5ks9vBstwp$LkK z8;0?X5nD&9K^{^>q;mNjB7ov26;+@lFdwHVF*%(!2c>}p-d>&;<9OBo@}dYYTw$Nx zg>vU;I~8|8K`a}d>lz5ANz#E703t4CtfUrFcqmNu^nz$H!%}XBVl@RG*6wuEY>UQZ zfW&AynL~oXNE&l;vy5hLnhT^M7eb#I=rGiim1GFD3Kz>Hg%$^0=X5i)g^U6(BV1OJ0 z3E4ai&t?SU(iGN*v2ho(fFV)IO}vS`2{8~AGC`(rSZIgN7P41ob?$_%pdv)vEnj{P zMF??dfFUAmy#SB>@pE6a?WHWJesDMO>-O?db9q&S>#y!NhXt*vUnM+qvUKITL-%F} zdfzqv;;n7?eRu1(lf4pyKSMvc?drK!`};nm0epxJ61bxiv^b9?&Lp^}B*M6(7Dgzn z=6@@3?w)*#olnyFmeWkFvpJks%10}3979E3urJCW2>vRV^SSr8pbMx!$G zfYMg+@hHf6Diwk}!ch=F5b<^`RmWNB;4F`{_46L zfA5P6T_;@3Pqpci z4~;O}jt-qb`pWwE}H>5(0IBr99RJpd=MLAz~dz!M}y23pF zXV)8p^9R&r&LO&@=uYcFDiAq+>`1Aq<7n($e7meuk-_o>p(EoVmUEbE3z4SB+gYxG z$O*yloF>=dthG2ag$3N}T@h|860%hx;MOH5@9)iTVyy7+esoIQ=Jx9GwGQL$#xubfXaB|vvdvBVeTRY~m6-j4uOjG6>cjk9Z{{TU* B$UOi6 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf b/external/boringssl/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf new file mode 100644 index 0000000000000000000000000000000000000000..15f124b4cc9cf799705ef462b9021a530cd0b4df GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW67#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZtX?mc5#jLMw)^SC t_swRnWyA7M-P%)}JmE=wwVl#wTlTl{7A12YGY9xBTtDMo;-?mSAppBIKxY5| literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5d64f19209be8be3ce3e914b475db34591d7a985 b/external/boringssl/fuzz/cert_corpus/5d64f19209be8be3ce3e914b475db34591d7a985 new file mode 100644 index 0000000000..86efae82de --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/5d64f19209be8be3ce3e914b475db34591d7a985 @@ -0,0 +1 @@ +ÿ( \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224 b/external/boringssl/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224 new file mode 100644 index 0000000000000000000000000000000000000000..1a757ff877d5d05c05576455d5dc72ac73184615 GIT binary patch literal 1502 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&e2?c8#|hO)MY@xIsXpLV#NKEno(+u0dE#j6lP(_p=1@MV^c{ z;AP{~YV&CO&dbQi&B|clX~=EB$;KSY!Y0fV8f++RAPC}c33IvU=cnhSDtP848>$*8 zg9Mp{W#ED(sYQ7uC8ep33K{uDnI)A9?nVZ3;=G2Yh6Y9!h8Ct~#uiaPu9<Xj4ta3oLii3yCIWZ?QEx#x)Gtp4YKm=%&COZ$WZ+>ZBNn&Q6LRe;MIow@5$nKIb z5Cgl5hd(zlGe<8S>|(v-{9J=b17S9Hpf}IiGBL7ofEmn;?95IK;K0%Vhq?e#sFM>| zQgBB>0?Q{=AqRJ0rIsi-mX=@!7CAPP7EQQpCJ;^F6tMwr6}D(%At{=2dH55ViHs&T z$vaz`#MAwa4WfU%lsjGLcQwi{l&|3Dyq^8lM^(%jWH`Wy6`tF{N?nZjaMI}gz8R3ePb23x&N{S7Ub>t@(7eM^L$0Eiea@g!y*W?^VJ?;3w zXusT)>cEVZ2t!#L8&E!N!)}$O9}a3=BX@1N=crogw)>lQx2c@$oF;KaRIu2j04d7?GYfh_$;ec6`yjKI!qzOg zMtG5_=s-AeD=d;+c;JS0rR=SU1D73c{^@$*=Jj4!b?N%62DKFzW@y$V-_-f=wflvN z;K4-);$Mmx3VvNMO+K@GX^XSSw~e)Wic?SK#m?Nbf^oU;whpVS?x5mx9dE5moF%uR Gm@ojGy`)P3 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/5f6a0d4e63e434e50dbf1159514610e031afbbc9 b/external/boringssl/fuzz/cert_corpus/5f6a0d4e63e434e50dbf1159514610e031afbbc9 new file mode 100644 index 0000000000000000000000000000000000000000..918ca124b6e50adddb371e0026c071c8824c15f9 GIT binary patch literal 998 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGk9raW&j3J2ANo`;^5(OPRz+n%P-2yOf(cT5CK`m z&co}QUz%5vn3<;#mYG@(cNY)bUGI_&B@D#C?&9IkP0Y;EO9#7HFF8NgAksjXjUDLC zbGA&3Y#d+)Gb1~*69bFnoh?n`>HfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*M#o6CV|Ynr2GnG_i}?&^RuupGqE=qWWbDJWMqjkh%(TI z@eP>TH4dNwG|g;Xx1d()cNqW z`-RFg!Gnt$m>3VlzZBCl6#TkintW#W(iUftZyRg%6sMldi=DY=1>^rY3>(@ste5+4 z>#(}&zK*xnCC-vtOsJG+`hOl@-SBy=Y)67^q6yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLs9|4dj8rD67mOVIbBZ;_)owr}m{yQ?I+n zRWmYrJAbccP2mx&T~(X99nLJgXjuNgF{Gwp*USB~ucEP;HHC!>)gn;V#BJyFw;uz?`Z9AKK|a?j6C&q)QP zAVXCHWso4VkPKX~B(*3nwFHq?72J(L$<@%*(7?#T(8AQr*aDPX%?u2U%s^=un0gH| zv0BB$!R4HolbM!Zl$V)k2u;K6e7wH-rFkWZnRyCfnW^Q5Fn4hwy9*c*V0ZEG=O$(X z0|@M5VDQK)Fc?@HSh8_wvjOuZI}@XrE+`y}fdN@wUXB`&MXAO4rA5i9#rj351^LC9 zCHX~_z%b%Q%Gb<|jSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgzd3{nnMSfuzg$Bd{S3bm;bWgt?fIh#m$8CulHXXmBiZZ8q9v6qR61 zY0M7Blf;vTOgwn-qKTRe|8OuKj0qkLc+nVR#He^Of*urGU}V_S_kMk!zQ5;r3o591 z*LTo}3K}isXuDk%*9E}miY;u*D6REhXON#MsXf!Tqu6C(#sl+oaq`ARlZCv<4%3835iNfVC$AVqw~rQLNQ+D4G(_$QenD@(!>Yqs&&@5qVTnqN3zF zA;!;ba#@SHs=%?vWi20$iYaem4bB^rhoK)h#_YjDu0s#NNPriXFJL_pceZn`9V3R- zW0-5Fk(oY7k?ObiwaUcNRv7s8rT*o`@O&iPSC;-gb!C>UWd$yFqJ?#zSLfa4HaB^W4h8dW3F7o*w_zhiFX7qgD-kC%l94QGE&JbW}%GZUHc zL4(odA~jH@%Po351TBnV69SfD5))Q^UjQD~Z*)1yZfFKKMIhIhYuKdy&!MMw-D511 r0vl}k$7zj1R6IC0bu)as|FqhD?{EHVbI;7@_thW%IHkRa@g4gI>(t@p literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 b/external/boringssl/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 new file mode 100644 index 0000000000000000000000000000000000000000..7d999fee773691ecc7e291f9ceb7b709b153a94c GIT binary patch literal 898 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI7oS27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1QFuAh86}EFm9BA6RLe;1|ksqc->R;LyAg^OB6iwlJyLw z4J1M0%)&x&ard13q{JKrXGeo3MkQo#Fj_M(H!<=v0L8hO7;Z5(Ii8V7Hu(ERTv;lt zF8aPrj>VJ0?G+QR>{)oj=f?`?ZOkuy71=pDZbj&)S!(WOt>~U>@q%@GR$bweXGap2 zZFt}Cq*H@`p6a!?&7apUn|OT2Nhb+Yk-2MUxJ}aYKlQQQ`JmX;aNU6Sow^NG;cGv= zi_gBq(7RLQhlr@@%>!hTc2z z=2DzR@Y5Lo9^HQd%4UDko}KPnVkyb6eJYdXL~g!+7J7=Zth2uP+U4`J%dXdv>rb$J z^vf(**z!u8n)Yqm6(W0$UP~}*1hEu8U2Sap&|){cSxeHK%2#3rU*ZpFzbMRp@{@^~ zk%4h>;|GJrw+8aSV3bv6kuVTz5b=1H@l*TKrm5H6ZzwAW_#4ldF#n2yEJy(#ix`W@ zfvOo9y`8^Tv!?I})~>2e-Er!Sp8-EeT9}dXKMSh?GmrwO4_SVY01Gftu^Cu_6v(p} z8yFhsFVJ0}-Nu4#7U!21C8rka7o`^D7iX5_ z7gZuB3RYGI=Eg>bvWG%>e%@k2Z3b+c8ad8?;5dG~ur5vT-J!QvtmXfI_;AASnzO}* zod&fM7ebpCWt}z?ob$q?Y;kV=4&f{A|GJ}MivO&;DQzTav3k0R$f{|VUN4pr;qctH w`{~5@&1SDqKjU5Erxtr50GX~qY5)KL literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9 b/external/boringssl/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9 new file mode 100644 index 0000000000000000000000000000000000000000..227dc49222f10698003c9813db60eca2be0a123b GIT binary patch literal 818 zcmZvaPiPZC6vi{NlTDf?O~Zz?R@E3l zBHKlB5Kk6Qf-LpuML`9tHV5$_f)%9oq9;*N>(N$G(3!QiIXI_zGjHbmz3)BHK*K#> zK_^BDi_QjGkjDi@6g1M3)|5wWHbR13<HL>V(~B!}j!1QT zc;)n~$J5eH9pynsIcTTa?Loqb9lboVT5TNFTHj&V!>&DqdZ(}B6`6MoPj8k>Y2|z! zu-M45-Gp%1rh#OBBh3$Rm}9*gkybBY+RNaq`y;q{s)P_Z1>H&L{U->x+9|1Od0#kO z&dZxW-wDSD2jY=XrlQs*@83wy6y$74oe(!)6vIkpqWrhICgLOBC(#d=XA3CQduDWe z__g85joexSC*u_m`b{ucpp!)bLi?e4kG|!7TOX}T_s)Hrx&JWTHlLgcLl;Z%lQw9j zFPU2eEl*)90z1#=W}LK00G858c0o664)kK(Kx4_Eh9FdTT|e)b`h{_8omcOvR}eG; NM%PBU)SHId+8-i_+U@`V literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/6118a3fcc0337a2cae92be95b87dcdc47a2c53c9 b/external/boringssl/fuzz/cert_corpus/6118a3fcc0337a2cae92be95b87dcdc47a2c53c9 new file mode 100644 index 0000000000000000000000000000000000000000..bef3bcf4aec026c4092ec72592f989a9d83d4ca2 GIT binary patch literal 64 zcmXqLFlb=Xcx%wa(qPccoUwpeM5MuRk}y-o0xM=FW=19^j)07BHB1IgOsbRlpBnJ9 Uaqj=Fx$~KZmZpJbgB61T08XtETmS$7 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337 b/external/boringssl/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337 new file mode 100644 index 0000000000000000000000000000000000000000..0464b03884aa0b14226c788d2a7b40de60a4eec3 GIT binary patch literal 160 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O`B367X+C!phhSIjhKQk!l1V488cA#0-yqoCKj+#m~BA&LV)J( iV`gGyVqzBB{mg)ujZ>@5qwPB{BO@y-gMr@yWyYhh_-T4IHvu7Ng4gj-kzDxwgqo?Kd#s^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhSIVqk7!-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9S6v5}$dp-`Tmx0q0y0o$fVj`JTljvp_qOMCn7&=qU>{~tb_@Vn-0 zv0?JX@JL&nTfam2iu=FrsF>nE>uyRLNm{I)ZX&X3+NIZvWkfhU yx9xs9@qM$|YuT{;Q@8dMCr@}%Uu~y!+LrxoyhX{J$IJnK3)jzhm-wm0UI+l*JwinQ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/65769e24f85a4467ff67707ede0c56b5e7046687 b/external/boringssl/fuzz/cert_corpus/65769e24f85a4467ff67707ede0c56b5e7046687 new file mode 100644 index 0000000000000000000000000000000000000000..1c812001363b47eda528dae6152a733127ca3924 GIT binary patch literal 123 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRk}y-oE=T5t%#2J-903{EYM2a~m{ce8KR4iJ zI@792<--N?V3RC3mlo57(v<%GrqyJKfP|i`xaurGoS$go8cuH literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/65b1bfb6b449b875079f932a6075771dba978141 b/external/boringssl/fuzz/cert_corpus/65b1bfb6b449b875079f932a6075771dba978141 new file mode 100644 index 0000000000..2d9f218a64 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/65b1bfb6b449b875079f932a6075771dba978141 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  ¿÷œ¹æ†*†H†÷  \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33 b/external/boringssl/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33 new file mode 100644 index 0000000000000000000000000000000000000000..f7e437abf85761a580e8787add01cd64e02cf0b2 GIT binary patch literal 64 zcmV-G0Kfk*fG~gpDD5zU1b{Gt18ATF6cm78k`n@Gpg{uy0RaL62r=dMd;&0n0wt3V WtZf!DPiC&Y>u^a*gR*c_N&>_5s{pi(mo7DGT3yj5gTe^|zhx=LXgC;2@~6bKz(-gcShZ4mqv^0XCP)!pa2(@f zXEtydOL0|$t$@pD9*OWtcN|`9Err76x>OYqSwQcOiX$)p7FzEjiytJza;xV^RWE0z zd!ds=G^2{N&`BXZb%4M%uWu_=@gr?8_~TQg~tJTbBJN&UXro?ZK| zd|S=WT=l<~hZA2eOgvwiF?cgOJS!(&KA7OHD<}a9ibK7Mx88|0mP{*+bUHnymRi4& zut)o@#H!xPIwdh{{-CyunP1bop+Q%+@xrip)*as@Q?7-XF{Vhp3|uiELijj@p|xlO znXz+{lF<+w zq4^OmjPt$W+PUzg2O2eh2d;%`HIYG;3!|lRQip({>G-5koo@gaKTvgcM|#|k^8&5Sc^ j?ob1Qr8^~Sqy9TTTlTrRckbicns>kK!d^s!hgSXqvG4y} literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/67f672ab618d2facc0092cd32837cc04e5d37216 b/external/boringssl/fuzz/cert_corpus/67f672ab618d2facc0092cd32837cc04e5d37216 new file mode 100644 index 0000000000000000000000000000000000000000..47443f783603cbb39406fa6dabe443bddd963976 GIT binary patch literal 1111 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S^olcNY)BU5^bV48*|h;^EIt%*@eC2fJ7=IX~AR(mo2S6JxeP6Jxr8EYL-=sw^OXaA>nJva+%>1MPycm<)74(t<3&5N$$tbdx}4UQ&Jq zvNyOvs`*)1n3>oc3^HKGFfy{l7(^Lp!}tbFZSol zmM|mZe-nrXQ4f=%n#m)i?YG%hgKf-#wgVA{gZN zFYo{7s9JOBw)+_i9Dx}Hlv4sSzSS@pG;P}5rgE}#n#2`R!D16PCe_LOPYw9lIQM^_ zvr|(;OVgmB==MQoFNLjHa*YlOizF8wxM5u>dn@9=Wrv%8x?Z?>y%%1({;FYZ#f2G~ zHOV)1KG-oBFn;Y;f1&bB@Zh2Y@h`;;1-~wsCZE~8w8dHE+s0Zw#i=LrVrTAI!MNOa zTZh$E_jSAm3@i->;A9KT!nH1OOdN(lx2aAxvNGVcLdwSP8L;FnOKvftQl9Dmd3<%* zn8W9>vK7X7iE@ID!3aN$cghBni?7ySr}TFni*R}0l8)d VhDK%vU=U@H3APGo5QbV8%To0nT3Vm;_f;5Nr^cM&W;96j7rE}VPs`sZerwT z0E%;IGBq(WGTb^Nk!SY7men;eTLh1)A8UfHwohR=@`&fAz@`YN(>bli&2 zPqWnA%UaPr*Wv~1_N=luHs>0WPdKaI4iJ^C=$PW=w)0+p}7FQRYn7IFBsP@?l)9vP{ zrJT8cu3571l;5)}SF2Y_o(;Ws;?1Qvi{Pg*{ynf(PbOwY2FAsW9}F7b8ps1fQdXHo!a%G+#N%1UPwh*a zre1fyp{yX_Z#-kd{3`~sAO(CZVk{yDs%B*LcK%+?n!+PkyQ(&I$Eh=Z2K*ptVMfOP zEUX61Knj#hLS^|u0xZC^#b#gy;>)ub8yFhsFVJ0}{jp6mqokz3N?$*@C`T_nHNOND zv3kk*xgddJ{bF$XNlw%Q@(lbI7%(w37#M)eP&mTkZs2O*%*Fy_GZ<;djm1V#7{@T8Rsx&5N>5n+eW&;gPmDw|mglC)So-9%*7v`eoS%ZPAzZrlBI;`?T^*Ro;x%o!=nr*7>jPM+|jzFKuM dzgAPj+P4OFN~dkv-^N#z%z4br8{oHaJpk!@TXg^c literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/6f0d97a3ed2a4c3c330edb10959f005a553d08f4 b/external/boringssl/fuzz/cert_corpus/6f0d97a3ed2a4c3c330edb10959f005a553d08f4 new file mode 100644 index 0000000000000000000000000000000000000000..2ef1a051f2be5a876301b17b42d99440fc0aac94 GIT binary patch literal 382 zcmXqLFlb=Xcx%wa(qPb}oUwp;ib#XuBw?nE1&+)HP0Y0hO-#=gFf*|-F)<76erCYS z#;Mij(e|B}k&%^^!NAXu+klgeIh2J>m?<>aP{4o>#NiTVcP%W}b%$sD$i2Mpg#qCPsb+pg0#(6C)$TtuqqI27kYZD@%pd zMc=o{v3OFry<*~(JqvI6{8-_X>n*Z>^EpI*zmsLNv8(?Jk@J&0oFcnssI20 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06 b/external/boringssl/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06 new file mode 100644 index 0000000000000000000000000000000000000000..781008a688dd60cae44b4125719ef2b0942cc367 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krVd85sp`osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZtX?mc5#jLMw)^SC t_swRnWyA7M-P%)}JmE=wwVl#wTlTl{7A12YGY9xBTtDMo;-?mSApihbK!N}O literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d b/external/boringssl/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d new file mode 100644 index 0000000000000000000000000000000000000000..1eb88833111f653293a66828ce6c6ed8d7c19a56 GIT binary patch literal 1958 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhV1NM9=_Xv=zu~BtEsQ5{6m@w7(>^ zC@-}{!LhU?BfluKq*B4%$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Wx;^5(O zPRz+n%P-2yOf(cT5CQp$orl*qzcjBTF*8pgEHm{IJP3FYLGaj6!axih1U&q?iJ3Wi z>EOW8OU};WoBe& zc4A)Fpxt#VY>e1ngg!_?2;b}pK2W%0Nn zDf@Lx_4zl8xQyDA^xwo@-dmlqxQQ{_pouZvKo;mCSydL0KRC467+G1_nSpjeSxg2x zAZbAsVB|HSJGx0AGcPH>0@)kfAl3XVEX+*o4F(x7V;C7(Vho}Tv|)S$rZ)MEl9B=| zef@&$OeFpK?w*eBMyh(rMI}h88R4pvb23x&N{S7Uwd5xk7eGA0$0Eiea@g!y*W?^V zJ?;3wXusFHnT12uS)tq*7361Ikd4 zlmtvjIcP-{a}y&YL#oBOc?2IMra?i`?Ssr-3R|<}8XXiCNiIBa!@5%TR>T3kISN~m z^#EIuRgAmHf`)|wo?NL;e6}1kxl#gN!9a@QUu!l3i(+*gMKL%V0Fw_q8(=0fj5LO| z5Ef>F$GikI=3#LSO_cNT6l$nRkrP~P!qehqhns)8UbuO^7hbylsv%m+1g6W{iVHJP U)23!kGJnC%=+Cf0XhsIp#T5? literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd b/external/boringssl/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd new file mode 100644 index 0000000000000000000000000000000000000000..5d1a0fee6d1bddebd7db3f8f2ed5c648325c38d0 GIT binary patch literal 1044 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*%A_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO=oCdPCFS)kRjsw^M}b7-?Mva+%> z1FZtFma#K48R&qd1yz7S*93DNFgQVuYZA!JOUgHBFlb=Xcx%v9f$VN>kS=}}7G@^) z27?Tk!HkS7F$Pfv+AzKWQ=5E7NlAf~zJ5V=CX#-AcTY!mBfaFJ5+ucpaK*_vnW=dt z#fHc_@{@}TAb#Ov5n~ZKZ1${cat@=Oc6?y8-}ME8=>e;+8t{NzCCt)b(8QdvfLTPO z!Ell=QwAgBe-SX?>ARYUCHvZfBNuu-PiHfy2M#> ziwTwTO#jd0s~bL#mF-BdO>}`t--SH;Pjgy#{hMgO$ROgIzsD_LQg!On%mqU4=TG+$ sZk#FkUAm4(BTgw#P=3$KFIJCuQq8uS>J+5Aaep;+k4h-gzF5o*0N|TN6951J literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 b/external/boringssl/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 new file mode 100644 index 0000000000..31cd941075 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A!1hö|0‚%“¥0  *†€€0¯€€' \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744 b/external/boringssl/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744 new file mode 100644 index 0000000000000000000000000000000000000000..67bd84067e2810c64a12cc9abd57eefc6338d521 GIT binary patch literal 1336 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 z+9u zEQXje7B~VU2NXL28Q+@FJ<%kPnU|Dbf$S}Akdgc>EX+*o4F(x7YZ)0?Vho}Tv|)S_ zVxFl@KBJ_hz)D}gAUhMuCVh8LM|UH=;{Z&^1@IJ$vK&+c_qb$2wgyX zYk?{586?Fq3+;Y}oY+`_iOmn50#Jhll4#>;lxW|;QgR76rK@01=^9v4x-~HQmtb=$ zFn=M%o?*r}VCXb44NRWk;(_MXCMMO%{7*q)4$ifBa|b+g@X<4KfU?Olc4k=KPyyx* z9LXLY=-ARfQ^qb}#$kqLoEl(ufO;G$SAgOJDEi!hpN(_>_c=S4X=t&7Gm55xK?5kW GFaQ9?Yg=&u literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3 b/external/boringssl/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3 new file mode 100644 index 0000000000000000000000000000000000000000..f5f7646e3b88553d6c79c5a9448eb4ab417db456 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC7?IBwb~-U-e6>9U~XdMX8?+G`7$*zGBVscBav+I z_lvl)R9Ic~eVZJMCxzQ9CSKXI@P^Ni70%n3U-~Mtb9CH_&`-0}+{;?gJ=fv|>-Ma= z!X?j+BrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@?>luH zs>0WPddINyQg&~=$PW=w)0+p}7FQRYn7IFBsP@?l)9vP{rJT8cu3571l;5)}SF2Y_ zo(;Ws;?1Qvi{Pg*{yn}D-Vb1Gkn8GMO9p#6e5 zyYMH|6GjHc#f={f8s8eo1A|dknMJ}ttU<)%S;kN8OPi)%cfX;mAmDF2W5WC^2C^Up zd@N!tA_uBwWb}6aUd@`qBUrntHg(6TGkymAAZcMn#{Vp=2FySToIYgvK>{qmM8#%c z1yUf-Vr*b&pua$Ofp(i_MoCG5mA-y*QI1}EYJLeQQuUJab3p>d`o-YHlbomrItbA3mJ$yXI`M zVW&Z@#D&o2MOmlK1n0c)NL!p+zeD(n`@im}nBqU{Zb}xtu~Lg z@4SqR+^h@+o`&28oNUaYENsF|p}~g227(|CmoS%metvpRs)A=;vZ1PhGDwhFSOzXw zl3J9PTB6`sT9T1plvz@#;BI6fC(dhVYG`0&VQ67$W^54!NzBYs2+K?@hr5dh*HCV}s})FXc|x`CX0j z3*{^LIj?6wL$%6LS@R7(Y7SFBf7`iew#DOyr0mx%)#u+V;xcMe(ti_sd2e;b;wHvy zgC@pw16iQevZ^c~2Xkn%F|x93jnA+qsN=gc>^z{p}Gm-S`yL&pi8|ft%mB7@p zvKuhM6({FprskCt8zSq-PcANi_<@f_j78+M*|V<6IgEPR@qy8P*B1z;2dutozyorX zFeBrC7A6A*19=cnnFSc=4I*B5*~Fyxe9PEc_O)@_?j)&QQH}bBiXa6FEK&v%K%HE` zkYHiFR>{Q5Xu!e7mfpw%OoavpASLoFng;3ystc4CD8ikH!#_D_$(6Z@k&z+Q;@rH2 ze#;{hd^Y~u`AR)t*Yo?55C6*N=`ynE2W1{QY5Z384Zp#1wbJ=_4`-PO2KoKV`~Nwr zR=Vx}rrm8SCp)J}ToDy4HYosS77bjvj*+S8_CaPZg{@g~jqv=Z=%BDja^Zm+)|Ili zA`V=3xcR5+g`3xVVb!JUuNu}?T$rI*lYCR>!`JQ?D$fKDE;^`z7VLht8K z_YrQKDfwNxj%PBz)>8w1HcoIEq@ks0V98*>s1c`>Cn&#XmwSGGdQPf>XI`?Qs(~^{kXcyf z4Nwr~!Uh4bV-XGo+IWrXHo~1zl3J9PTB6`sT9T1plvz@#;BI6fC(dhVYG`0&VQ67$ zW^54!ziMiSCW{Srx2Ez zS`H5h9^{aaFc1TW1P_01VrGtBIyj8{%~0PGf`2LJ#7 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 b/external/boringssl/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 new file mode 100644 index 0000000000000000000000000000000000000000..5a91ba118b18a4bbb755f6b611c21c67b9945c63 GIT binary patch literal 1492 zcmZ{kdrVVT9LIYfy)AuEOFQH-pa@l-?eCVy3Ue9Aq{9G18BWW5l;+Z2sJEruZV-f& z#x*{cCF<0fF|2G3mn9o61H;3i)BQoVI2Xk!n=#w8gAKzn1za+9_f}vv+3sKGoclZ9 z^Z9+x`Tf8PUNr3v_;4@yQtScjZMBy?phE3|Vhns(JNVFG07Hc+ibV|vK~6+u_+RwT z%MnB<6hI{@g$M$x!3h;wQ%x>|NPZ$wiPkoG=z2>FnGKozid2=lwuzIw%E^6!p$LkK z8%Oc=k(3^9FztYczbwWjN?`R%ZnnsaFu;- zC(50pJ*c=13L;{3zH2a;CP@cU0EoDZv65Oy;h`|q(+i?y3`@Bgiq#Z*Si93rv#lDF z0TP$X$vhGaM$(v6BRg)pq8eA-slvo^ez0=Lm7BU*t{81vA zyu#^WSPRW)HqzAVi@_2ZpI68#O*LipxG7BuQRD0)|8-H}NL&Cd5E=$OM_fVWAy5TgYCW)wu&UgNhJww|wzA z6d}Z+0fvaMH3B^L$IpGsZ7=0O?ft35uRAKo&6PEguD`n992K;sewFY{U-`)S{KSMvg3R4BJfVmK@SMtoxcYp4aPL6}qRZU2zP9rF zfYMg=@i@qMDiwk}!ch=F5nn#|7)|I1H*N3L*`CBB=Z3pJPu;G zof6Io9J$(x3K0+!gsoG?J!}9zBneN4RiF)|1d^8s|0f+sc(qD}0?daX0?K%?`*>yV z=I!OD9uEGts%q%ho3TGVNMf=PLcf9jaxCYLc3J_wD?P_oXD=6B z|9kIb>AD$}_Qa>-WP8h{chYxSuV?)+yH9y8bu!p8%*pT{v#~MBe_w)&gmClt*^tk*p&7m2M$%p?Y<#i*ml~_B7|db%}ZY z&#pIy9`09HI7jHJ(%WqZs6f=ru_NWG&ZDvO@g1^*iVT)72pt&@v7EzPTZl3}-p+Cj zL{11sU7CD{v(DnsloWHXcSX3ZNXS-&fLoWKyuTCQ#8~0Mz2zx!8#`)mu67u2HJxtR ze`VzOwetHXO9rs1ie!;^_rxZBeL?yeVavYvjFZCC4INEg9|SLK|8Owq&k$#LM{8>ij_vdAKp>M`}YfqY@TYJ@IE0xaXneLdkyEDIQ{s#{} B$G!jn literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 b/external/boringssl/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 new file mode 100644 index 0000000000000000000000000000000000000000..b88f394222246e6f1defdd866ef6f6375beababf GIT binary patch literal 1777 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB2T=OsbRlpBicz z0M)Z`a_s*;XXi65O`B4Xc8#|hO)MY@xIsXpLJXRi_ALOK0W>0eKT9BAq#ld&KxP|)oCnkka-IRN8t4A+2Apin zp)72|OrgPs!Ulps4u&%@?ZME)!X?b*o}ZuYld1spYEE9Vp{jv0&@5(Q8IW*Js)A=; zNorAED$MQVTLLjG*#Kez3$qN=1|*ZMP=k>K_X8b@a6Ai!>q`_IOG`5Hi!w_p72J&s zJLnAW-Fo-h91V#yFP;u~ZIVa|1rsWsqWhNSm8HfPG z=>j_suWx?opN;!7^Ay4|Q_Ded;RcKtE*@~Wf&(zwP{KeAsF;PBhd(zlGe<8S9JG4L z`MCy>2EuIYz~pewmWh##1I%D%WM_6_V3EADrAa*9-`F7f$4j}>b$(Z){6hH(e$MOJ z&rq#$RMvchkD9~O&);?~nr-p8Au0QHOZE9Ti@1#1l=R=kUfx@svABsb+n|Xt-9Q#- zwX7-&$iW=iY>cd|?94!`pe!Z>9gwsj3ou%m&|TLgkeQd1UjcG2EFB<+7`O92x# literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224 b/external/boringssl/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224 new file mode 100644 index 0000000000000000000000000000000000000000..65c09fa575357443cac757b779bf55afb27cba0d GIT binary patch literal 1081 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?+|g|l$*a5*RDWTxd8USYN!hPks?Wb!#AVc`r2i)N^4{u<#Z8Ra22G6V2C_h_WmQ=~4(8Bi zV`ODzX9ijYWic7(fTRUkfI-)U?z$#{%)F%h3S{?kgH-dgurM>RHyC8Fc|eR|WMqjk zh%(TI8Ee4QCZADKQedU8Uyz-Nq+j3N)6v~XFS)1$Niic_adJ*(YFFen9~kX-eSu(l!0M|8JRnyIGcx{XVKQJakO%RUS%87wAmVkG zO-y>vw~Vc2UmLgWPLkRc)u?Zv2vVTHB4r=})X4?(0t@4{N+woD0}eK}^hO?FDl{+v zDUoNed0uFOr0j0~w}=jJW+TOOI`~SLy+~p5K>zxc~c{ zod#`x<@0nI+4O@l51llAtNMoDV7Xf9{JV#xG-wd*P+)uNu}?T$rI*lYCR> z!`JQ?D$fKDE;w;bIHf#6`8@{o&&2?nlSyI# literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c b/external/boringssl/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c new file mode 100644 index 0000000000000000000000000000000000000000..8c6be702bb6551b74488b7952aaa5d2cb85c10d6 GIT binary patch literal 1432 zcmZ`(drVVj6z_NM?ZZB(rCoUqDUT}eo?9NP%w-^x4gwv@bW-M{G?(^DZA-b`FbFA) zHY&>!W$Mfr7B+{=l1-PXL2=-8e~>NCMRDq8$Tsa{gRo2imrU5byjK6%{p&mDp7T4u z^ZU;Ezz04obsYSJ5B$mYApVZZM;=mQ_FxeXe!Kwg8teFp_J|E^jGtgnBPF0Z$r9@J3vBg2xxjatVLaIT< zl@dy26)vxnvCvM^)t50Yd`O+yO^Id@YZN`RNOPlI z1UtjH3v@bnJsk$1GnN(^_1RVr6Bdk?f~^jkax#r%c!tZ`=$>yPf>0Bx%lV-L9S)S8 zv2A^g>4%`gR{6;=NI6_c-)Twvt$3xSlO{YRp2JfmpLbwl{-sn ziRm7^_57~*JDUfu7vBEoz=M*q38nVLXTxMm)3tZgc3W>}{yEvMxRmlB)HAqkR81-- zgGUnR_7i)GRa2*1vJ(#vIkz0^KZ$xP&h9H1HhwB=d1>ovi8|6NJvu9`$a<}dFSt^* zrp8UVUiEkzbKkz^eDSZ&z2|2Rsw!OlbY;o?=0j94a^m>Wa%J1GnCZAyX@@+W;hu$T zG7e%`h1qu@(m0>a$nUcf@&=|gMu)4`;?NWqvE!Q*E-RXoRnBAmVvN)G&bQH4c=9MJ zId)TP&Bz*u;avtgBm{c9GxI{=VS>|J;t&hRzQ| zSGIrD7Yd|{(tQJPALN2%1Jj*-q15y=Sj_{Jx;4qENa+9gQNb@#D*sGgrVma{`0njb Xm3L`xx@{$r$voq@dAld$`$qg1S%*;~=%S`LHEluL-{>BE;KVHh6uJgMZDPDnbaXe;OD-xgXkuwFXkyNQM!R9gw;I*S{7>l;?dGNi zMn)LXo`E&mId}+1dpWjfPc{@c5QRiLUwL^sED)Z9qP>Yx3E88JtPIRejQk8haW1AN zMn;A$UL7-aN*J@Qc!_syQ!;tDed3{Hr3_*FFNWb~C*C-@W$Tx6$tuP4jxU?-&Zg+| zp4$Iifk&G8wz{3$ttS3|jgGAj>-PNXU9oi8q>u@ZE|wgVTYApU$e(3r`o%|)i=}IC zW{7V3Fk#7312Mb!tefm27u#6pSUf0BeR9QX%I3*WH?b*;T>1R`yyi*Y;+;{#h|!0|Y*Ou$_H%y{6=5%X-7i(|eYig|sg?pcQ&~Vz}M(<{6LO zQ@dXn&2T<@aAWuKP`P5hM*S_Za~>W%zg#bWgF!-U;&P_#d$M2h?qH}mHUC#Zulz^t zB_EbC6@5`QeNZ7IY0JdS$iN6pz}~gOjH7eG=w iAB#bQK?9S97>meZvu9nCa~Sos-x@R-s595b2Lb?-4qV>= literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/7685b3e299f2cce95aab0d8559fd45d8198f5da2 b/external/boringssl/fuzz/cert_corpus/7685b3e299f2cce95aab0d8559fd45d8198f5da2 new file mode 100644 index 0000000000000000000000000000000000000000..7ca6b0944757fd66a70eaa8392f2185980722a68 GIT binary patch literal 10 PcmXqLFlb<601|5f53>V6 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/771688184c18822e2182b18bb1ec853a88262659 b/external/boringssl/fuzz/cert_corpus/771688184c18822e2182b18bb1ec853a88262659 new file mode 100644 index 0000000000000000000000000000000000000000..ac6e9ec7583e9d9c3e6bc745e0ddd773195b7633 GIT binary patch literal 15 WcmXr$IKf~b!_r`_)x?~U!VCZ+^#lq4 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/772739edb5a338fade2b33ed8c4c7e5c3856e7bd b/external/boringssl/fuzz/cert_corpus/772739edb5a338fade2b33ed8c4c7e5c3856e7bd new file mode 100644 index 0000000000000000000000000000000000000000..1ce94e494ec5bcb3b0bb1bed157993e8fcef4712 GIT binary patch literal 818 zcmZvaO=uHA6vs2Olg&qyre#A~t8G(bY_*cSO=%2@VD%6yHMU5Eri!#7W|w?yNVj6C z$aaw&#FNF7AWJ=ZQBc8Jn}c`|!3xrP(UYi%^=PXo=*(K19Gug(#{T0_fZ-=y=KCFv8fLtCEq%(dT2}<{f)0$0{3cgc__C7!(`8!E;H% z3pja76rh;}PQe*hlBDi_Qg^(jDi@6g1J&4|5wWHavmMe%jcDHQ63k4;H6TpY%cc+W$Kq+tu7g- z2Zpd}jq*j8{PDH^E?mP8J0S?T6+){*L!;UtE_ST=+Ko@bN_3LTWY)T`a**+Mt!b zWNs0(I*qLe>^z^Hb+l3***0uRc((AZP@P MuB~#ZH;(GYANC;HaR2}S literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 b/external/boringssl/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 new file mode 100644 index 0000000000..32e7bc8401 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 @@ -0,0 +1 @@ +1ˆ0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9 b/external/boringssl/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9 new file mode 100644 index 0000000000000000000000000000000000000000..ec01b39f3744c19174c198a14daf672642055077 GIT binary patch literal 10 RcmXqLFlb<4GI-dq761^01EBx_ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/78fa5096155d1b72a074a486cf7ace40a4c92f1f b/external/boringssl/fuzz/cert_corpus/78fa5096155d1b72a074a486cf7ace40a4c92f1f new file mode 100644 index 0000000000000000000000000000000000000000..5a9acdae2b3171d5d72a6588ec1f1a49790b4fcf GIT binary patch literal 5 McmXqLU}!J^00bogVE_OC literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 b/external/boringssl/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 new file mode 100644 index 0000000000000000000000000000000000000000..31cf984926be4433469c8048b65615dd87e42a1c GIT binary patch literal 974 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OkCWC z0tS3+%qA>c!tAbvrI~4o6^6P7+92sdVHIxI(oBN}g9e}|mqKuAa%oYjf^%w7NoHDR za$-rUf@5h(Mt)IdNu`0DIIn?`fvJ(9fr$YSM2YjNTNqftxdu*POWDDeh6Wpo8Hj+a z;1cF_Pt6Z0DlINi@XSlrGn6)v1c@^X3&F+RbMliCa}=B%4VoC0kp05Q%D~*j$j<;2 z=h9?qVq|2vbw(oD;O`f4WvQ^b==(M~7EcPdS4_OJXWA1j=}=B}OLHc8L_ z)W>$`gJM&|bpzga>NZq`ul@8cKKl|w?@o~)BBG`@54bI^E;=!B|H)A8vlph@%~4A^ zbN^hkWZ@~lXIHLPuarC+dhf)WOK}##Ph)ub8yFhsFVJ0}-KLpQQc_^0ub*6$qnDnVUjm9%z2y8{ zkU+71F*x-kC+Y!t27U_+m>3!i3_wOG9AR-ca5ZpdV*#=m46F?-**LV>fGL%oiBU`! zWM(nY(DL$fR6~nWi}Op1l2eQIi&6{ni!)2|iz*E?P?I`yb0b69L!mrBZ!w`Z1GY^a zCm0N5SQ_?!Z(wNH(8SVU(8QcEXD1}5XmS`DWLSUuKW9UmMolBf`41e&j~CXZSvR~p zWB}7=t=07QinaXz4^-ywX({a<%fO!1#} zH>HgvEmluA5m`0u((A=CA{?IEc0Zl?zS-=xY*;>XMhf$(TYHL=Cp@XIR-MeR)zq-| Yt%04=X_$^!y0E>!Qpa1{> literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/79fe694f60433debeb203f01dbacefcde6e9483f b/external/boringssl/fuzz/cert_corpus/79fe694f60433debeb203f01dbacefcde6e9483f new file mode 100644 index 0000000000..35b47e8ba5 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/79fe694f60433debeb203f01dbacefcde6e9483f @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0 ¿÷œ¹æ†*0€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1 b/external/boringssl/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1 new file mode 100644 index 0000000000000000000000000000000000000000..51b0e63fd228f5582fcadc5fd3a2d5ce70e4a0de GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a`8-g9`3B`ALa63eJuOO^iy&-e6>9U~XdMX8?+GFf}nUGTb^Nk! zSY7men;eTLh1)A8UfHwohR=@`&fAz@`YN(>bli&2PqWnA%UaPr*Wv~1_N=luHs>0WP zddINyQg&~=$PW=w)0+p}7FQRYn7IFBsP@?l)9vP{rJT8cu3571l;5)}SF2Y_o(;Ws z;?1Qvi{Pg*{yn}D-Vb1Gkn8GMO9p#6e5yYMFy zBf}HM#f={f8s8eo1A|dknMJ}ttU<)%S;kN8OPi)%cfX;mAmDF2W5WC^2C^Upd@N!t zA_uBwWb}6aUd@`qBUrntHg(6TGkymAAZcMn#{Vp=2FySToIYgvK>{qmM8#%c1yUf- zVr*b&pua$Ofp(i_MoCG5mA-y*QI1}EYJLeQQuUJab3p>d`o-YHlbomr8wHdH&YUDWof#dk`!n(9~hu&VXmjD0Z!wJ7@&K4VX z8q`W$2yI@Jb=pjD&I^yU#kuu6gs-^&>yC;k{ggsTtEOFgy;w$s!*kp2 vrxV{do4u9|%RhB%PjT{uC-v2KN~dkv-^N>%%z4Zl;J0x7jCYBjTI_`Y#qL46 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144 b/external/boringssl/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144 new file mode 100644 index 0000000000000000000000000000000000000000..598723ce56b96063744336f0fa06a3dc4f6f3737 GIT binary patch literal 1098 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 z zPDnPCFc1T~i-$kg;MzU|rY7d5A?(|qK;M2>Aj-FinK^pt;Hc0`&d)W7G!SNE2S(~S zTP8*}4lsk6k)7FzfkpDpmL~CZe`AB_A1~!j*ZEzI@(blF_&Kj#Py3YZA!JOUkc6b}u(bH9rdrGZTA*K?ckiMn;wx z1NA5aZJ2-oQ=5E7NlAf~zJ5V=CXxaA?w*eBMtaFbB}j@H;fj-UGE?(PiVdMU)){~@ zh`|3jA{*K?tQ&v`_5tH8YEn{oh*T!vN({;ev518fP*^en>fg>>IH3G9< zK*qNkCSX=noy`B#Pz$7l_c=SCX=&P+LUON06AP+A6z5%N9w9#O?luGf;6WoT literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847 b/external/boringssl/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847 new file mode 100644 index 0000000000000000000000000000000000000000..90c6010154d4f20fbc4cb54802f80786458a6dfa GIT binary patch literal 1221 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|6^CdO<717O%{QZaBr=231O^`puGHB}6; zs9Fq)swT#C16g1ykyT{@r7aF^Hbz!fc4lCzfU=kjbU@OAEWlLWgr1O^1TyoI@+**& z7B@&WKMM;p6MKU}2Fw^nMwS?ZC^$W5yk@V}kdpf!s=_MDHASq^qD^AYIOwB7PHbmBupIlr3@dF==7>meZ zvu9nCa~Sos;{&4&8VnkkG~OCCxilCYV$N8=EaG>4fna*T>Z=AkAa@EgGX7^_GGH)} z2l13yfYHz(;&qozOnT3^jICu~8@KIFlG+v3sBfSMQlP*hWgr36$ps7>7RGCpOstFs z9BgdqjXc0~XH4dNwG|g; zXx1d()cNqW`-RFg!Gntq#J?0X6#TkintW#W(iUftZyRg%6sMldi=DY=1>uu z-PiHfy2M#>iwTwTO#jd0s~bL#mF-BdO>}`t--SH;Pjgy#{hKJ_o4>~`U{ZDJ)64}z p@8?hV5pJ9*`CYn>M1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|7vCdO=oCdPCFS)kRjsw^M}b7-?Mva+%> z1Fh1217R{5=z!z}S%6{Jgzmg1fy}(5{0d|TbAwd#v#>BTu{RiGz)WOhWQj3|GSG(c z4Vc>GGfGMdtn~E@vNMtN>$`h8x*O>w7nL9>W`rwF&dE&8D=9Wa){&oFTmbO|ABz}^ z$YHZ*U6XSd^|a#yqy4Tg5KIqPebs;mfV zv9;`L8NW-o=U zS#pgI3X3Ec9=Ks$DSIp8z-5PW0r_WjhjV6J21^cOlRI)11~_|0as~=I?O}m{gtmG;@K_`}xy-gd1l{ewVJ}(TG#Z o6O`Yx@{83Yp49#S=j?3LFxzUXQ(&F$#{JdQJu0C{`(iOO0G?GiQvd(} literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/7ecb46c93915184be12fa3cbaac3b65072116242 b/external/boringssl/fuzz/cert_corpus/7ecb46c93915184be12fa3cbaac3b65072116242 new file mode 100644 index 0000000000000000000000000000000000000000..2acc67937bf014686438e167f3475dcea0926c8e GIT binary patch literal 64 zcmXqLFlb=Xcx%w~s==U{Ib#8{h)9FsBw?nE1y;;V%#2J-903{MYM2a~m{ce8KQ-WI UrE>ziNtbL0N~`xL@5Q_JD*;sLu0?1W@P2?H^(yLk9>6Ek!4(!q|?OU}z3;CZx(SGwJGVpiM_nHI%9DYW41vPW4eJX&}vy# z7LbEEwAmP0S=pI^RzX=z200*UK^9=pHGy4cjc{F)KxST2eg(37xk0M=Sy-5v*c%Ko zV8$>qvcwpuM;U0t1PqwkwQ<|-B&l6djrsdn@9=Wrv%8x?WhjdA%22y8fzRZN-Hdnl;Hcbv}IUexdSA@Zh2Y@m4Rz z3bhL7Zm0VvP)35E#di}Fv zz6J<<`d~Zz>UvGd&6f3snWy(GHw$TBa6l{c^2Bhv>CH19yIZApzc8BNeD>hR?&YC! z#e9wWTVm%tJa~S&Uj7DygxJL8OxyQlzvSJ)P;qKLFd=|)+^>RO`H$L5J}hG@`l4+5 zph8B{mWi2>ff1N;yn$ik4oNwxETE*$q0Pp~%F50ROr%g2lR<+)1Cz#EM9LBoY1p^G eaFQ@n#sWuRUIu373`34@HB9Ix!16hVHVXhoqdMFG literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb b/external/boringssl/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb new file mode 100644 index 0000000000000000000000000000000000000000..a9b39dff50be458f370533fa346cc8ee2575389e GIT binary patch literal 193 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 zyYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtB_wZDF|sl+H!<=v0L8hOniv@wZk>@xHu(ERTv;lt zF8aPrj>VJ0?G+QR>{)oj=f?`?ZOkuy71=pDZbj&)S!(WOt>~U>@q%@GR$bweXGap2 zZFt}Cq*H@`p6a!?&7apUn|OT2Nhb+Yk-2MUxJ}aYKlQQQ`JmX;aNU6Sow^NG;cGv= zi_gBq(7RLQhlr@@%>!hTc2z z=2DzR@Y5Lo9^HQd%4UDko}KPnVkyb6eJYdXL~g!+7J3(DS!aFowae#cmtC(T*Pmed z=$Bcru;rCFHSOEBD@67hy_R6s2x2LGy4u+Gp~Y@?vzDYem9NAMzQiBUeo>hHWDB4HrbAmZ^X5)W*`MlAF}))0Ty7QVl%J;DUfF| zHZU~MU!c1{yG=8rq@=(~Uq87hM=w1!zXTMiddc~@Ac122VsPR~PSgYP4E#WP6?o# zqDrJh0ZQA-W5_A9n literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1 b/external/boringssl/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1 new file mode 100644 index 0000000000000000000000000000000000000000..4463be1214d780d06306e56c4cc43350b8d23b62 GIT binary patch literal 1642 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf?MoV;X1RRd*^AhWOxRM0c8B(*3nwM41l!qCFh%-A9d$Tc%CG%_;)gD8VctX6UGa5*RDWTxd8>)fVIT%}7Y~1KVrGtBI@rZ}m-2HBA`OJu z*n!?WXUoLM#sOw9GqN)~F|bJ9+0rDQ?r&@m{o|$F={mowQGTI(1wZHY>}RM}IVx+u z!AH$u>gR7e7tOYK+>n(0x~2O3n?+nkZA$uYVlVHl&RE>Um~B9vpappWN6?m(l%_f= zz=GDGi80+k7U)%3RTfYHacHwKva+%>1HA@iF&XG60;L66faW!!ghq0HZj(S}UQ&Jq zEPQ|>2HcuJ)%+|h%uMVJ1{pA87#Ue&4Ai3xv|$1UOl|TRB_#z``uYXgnMelcyL&pS zyBp~x7nLBXW`wIw&dE&8D=9Wa){>uGTmbO}ABz}^$YHZ*U6XSd^|a#yqy4Tg5KIqP zebs;mfVv9;`LzSimeI z(qK4Am?>j{BQT2q)k*|pe5+vs<{8z={7((|*$h+{C@)Zi`w24yzyXkh$Wff&EXCZ! z$jFdtac-l}jhkxbsbQ#(7gE9}DG=8i4hTmYhS}D=l#sM{l zV#_v~kZhAzf|_kgS-1#goB4MSXPF8H`TfiLukksmR=Vx}rrm8SCp)J}ToDy4Hu=8pe6N8^vsT))ENa2 OE;XS{8kuU)QnZ2`-ZomWtz89b4*je2fq5YgF)6id1cjCEd-9?I1zs!2+@*J&jn@$?nGmlSS$hy6$zsxL_R4|;Q4t}EW`+l z2!(WpyTW0!R#9o76_iND_#s7;$1)WjR%2p4yu;>TtURlkR>9jjkAq(hV-upm02u}f zCIh+(5~3*@=;0+ye|$d`D8u_jn_2EvPlcD)t-icY;|f()4-37 z8`%aX77>0-E<$<)?!z$Ag%gPk{Cz7S<>~pgg%@9R(!K7zRSn$-KRGx1?sn52;@X^N zq_Vdzyr#EhPC6v6TC<71D&D)S*1a|O?UHS6H+{XUQ{|f{^z_&Nxoca)(Wc|m6El>X zb~Vl1pv&#}{Y}$Xs>TIrb8oIr^Q~C0>yI0v{avN&ij;SiPi34xGPAYXbF88Lc)s@J znT=DMCoVm4@l<`1yTcOfK3n~1(#iZ^j$Q9sOy^zsAa`xrgSjcj`?g@`J6ki8M0*?Y z%!bIA2ej^cwfMu^bEa}~srvKh$G*D+e*Mdsr|8aHJW=~o_IBkVLti41`U>g3vNJvV z5`92wTvgn>{5KWcDmtRQN|d?>@m@@Xwbl(lT|XqF->6O@6G7!u&I;NGwOzX#e>9&< z(ZuGaH?9A;8`MHT45=cOM^-f1*R8&{Q@k`Pu4YFKyRYMf1?0kO1%^E&#Xz82$RBFC zAdtvZ5||PlFS7YkDn0;`-F33l1G1w>-LeH=s8@){V&?v z54X&Bu$9!KvZ6v|g(_eu2?rxdq?xXy0toxb3-Q~ z_!bs|LLx;o^HetSyDaoTU{Yebh)nwVOMgO1ZaNg+y*9S9)^fJMk{?q(xOr{6sCxW& z>KEFgCce~o@Am#JAJLb6#if0#s!w0v5@868(_er6heOr&RzFsXrdCN9!U?2sJVWLu z&{km#2ppUOCvhb5iC}MfI)ALgRm@e5tT$4KmJ4`FePDl-2E)ij@N5B^=0kY_ z4^X3y;by(DPd%UOxNy+RtnXb}J#}1o{(NH$zTKHE?JuJF O=J%YKPFr+&Ug1AKpBQ%l literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/848426625248d49961481ba4616c501a808983ac b/external/boringssl/fuzz/cert_corpus/848426625248d49961481ba4616c501a808983ac new file mode 100644 index 0000000000000000000000000000000000000000..99dc6cc105191ea372a99aa81e42e141da17fb3b GIT binary patch literal 1055 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%SA-kFzq=lb_g_()H!5{->79%4| zj6sxvHjHn;)Fz)%Qc_^0uV0XziKJiO-P6(CNH4jl1W7R?Tyb(vW@=tZu_3aK{N&;S zh)4KX#8^ZQn?38AoWrQ69UmC&cYT3idcf+d20S2F2{SVOXJIm6FpvlFlv#j5-yq_3 zmyJhy&$o=NWnUY&?M{-~71gM3pa@c+z#?TJ0o2I_3=S5?Yn4o_j0PNRZ0U_Wz_e&! z08%2)qG_ORpt?YLfg;?AIQ)}?mS~xq7#SH-EzZqb=(jvF!Dr*Yov+jbc0Io@`S7oN zo-QMseo*G2lg4jV-|!nOS1X-=_i&bpV36Oxy#Jr0YNgxmZ`$3aaVdg12vUU=#HtA@1|7iMVIB;VBe@U{De z$}_=(iw?xU6f+e3x?q}oX7|z-XOV9kYxNYTp3IA#xn~9Aa^GzoR#)BE@ft9&G#E57 zXMi(dtxFsehhfII8r8{0RtCIQNEz`x1D4!j$t@3nxZ~h*)fJxP2zYN}I^?#BJq)IBPpNc&yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9+&(#wePRY85c_!DQ}aWLN{dSrJoA$E z45bYuLE_B9LU3{SocyH390g}bgC<5L173r{<26KxGO{u-H!<=v7%*@#GBzSY7men;eTLh1)A8UfHwohR=@`&fAz@`YN(>bli&2PqWnA%UaPr*Wv~1 z_N=Jr^^7+|i*XzjjCs;oEWfm-Kc_mIw`?l>0k-bK*C73mWSPGx6Hnx3ev76nj zC23COD=~vF@dvbDFlQJ3WMX7^!nnBcgF)k419@On%PO--7>G59cs$GaseNhF)a&jy zlobU0jb}`lf5ku+q=1h_j78)?)r^eZ&flw9Q+NbxSJkHOICaL)fFC3+%*gnkh1Gx= zNP*L^EI&wq1(@*J46Hy3H&EMejvRHEba!b2F`3OKqiBMwSgrYhc+89|FAPLis^#PDh3)>US5uB zSW#+merZv1YO#J%YC(Q+W=Vb#&@f=;A~~@mQdlKg24-e-g(kTsMlOaXMn(o|COK%z zYHVaEdnlCW=Pf4GX27mUaj^oD*>(bsGdV9rM{{M#$C;YBCTWr{AP%CjEw0Tk1 zX*0n&FFeu~=hp8KzT*B*D=Mb=&$^q^Mv@k*r<;hZns({+Vi^$*&uzP(PJB;MvNZ!H I+}E_8s=+{DZry>zhC^^)^*4I&MM+1P>p zJ!i|r$i@L?Ff+0Mt5JTTd<8$}_3US;RyitbzQIS$ zVe02^I~UEic-)Yb{ko<4{F_BwMr}&^Z(=X+td87gG}>Bf}Q2j+r_oj9FK_#JjdBnLOM+@ldi- zhOqq?!|<~cZ=Bq+^-H;Am126wm(6x(Q}oqO?f+S*p%U!!=Opz%ID|jO}D$gdC7kF!JgC6${kj6eRWK~wm0kb&w>;&051bW A9{>OV literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 b/external/boringssl/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 new file mode 100644 index 0000000000000000000000000000000000000000..54e2620348023585019bf2993cc1d9b559b61768 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eAQG+A>oH8CkjUNme-x|mRgHcwQMZ!R=LB!)(#!u}_o2FiOzoD!k;BP!*!u%@+vLFR~EMhDo z2dZXd^mhJU&6>g^Si7n=b;qeQeg^y?X<j9K4kep0xZBp#b#gyQXtP_ zY+z`hzd(0^cAI8KNlAf~zJ791j$V3dehDa2^^)^*K?244#o)w~oTvxn8Tf(pDzLa4 zxEeUKu>hG22G$0aY#iEbz_iKE#3-fDdCHRZL9G zLc5Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#NiU=a?j6C&q-A{pO}RM}IVx+u!AH$u>gR7e7tOYK+>n(0x~2O3n?+nkZA$uY zVlVHl&RE>Um~D{P#F%a%3$$BSl?CKt4sA9@R#tXqpj}WFlYtIMT95@8c1!~m2gR=hP>!~(Pqo+Owu7B~V^11LEJWPGb(0y-lV5rv@m zGcYnRH8M0X0mT?7{wxeE;9LVI)cAu&6_+rtduo12QE73B0x(ka45bYuL9SyK76OWc zh23-VlM-_joE;6C7?qHH%gD;W+{DPw02Jq9YGPz$xOGM%+2Ai0cdAb2e`>(b#<~Cd VoSm8)TABuSU&NKA!s?>$0{|6q$X@^e literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35 b/external/boringssl/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35 new file mode 100644 index 0000000000000000000000000000000000000000..51c9b6da7445a485afc7956893d93b1bf3891b17 GIT binary patch literal 1849 zcmZvcc~DbV6vp$GEQZaP7(oQ0EV2kWFF+ckc0@)aRs%|L0V_fbb}MC$kZs@4TcX37lA?0xh#GFPsp>fysav!U0CHumqgNM-$=+KJe%Tm(P{! zbm^iuOcB zf^*iZ?Hd{y1wKD}d{j5rZ+gYk{`%_gWPg}aGas!jxY|?Al~^W;dp^H@sz6<1Ml!*S zq=N@_w1=+`EtnI;LYPc8Mjb^z?O|gmOrc-%e5lfyht+`@E2N0nhKOJdHhUIKiiN_i zK-_p@G&r-cFp33xW_AvlmXb#VLlAvo2fhy-0TY<0C|4A(Qs(GYqG*-gNT!j>6r<{Y zFfk+Eg7a2KDa+bDlj12f7L_IF6xg6R3v^g&_D+NTlxau5f@_ywpZx)>N@LE0eU# z7t3R!Myy&;yIAt!AV9p(u(EVh;`pBy1#YY=b$Dc?n z7Q;k(g9slFuGE*f6mcBs$VZt7a9FJLVn?dm0O&1VcmPZWU#quu;)vuA-%ljh=u%TO zqUb2fT9fQ;fiN&L;=-W9+yK;!AdFj=T$K>`=Gi#!@e7NRx<1y(?qwg#D{niw^XA-_ z`{YNl2lFPfIqPmM7N0YV7%XZ(6-jb(#%FkD} z%y11CY&%dnYg0(I3hK_zy!Q&l5C&3H+y}+I@1dG)Q@;voJzQ}^e$!ht zIySWOn;mU-Mrc}Hsoq%nZ!L3$Bd>6Oq3ZaBOA2rqGy)Bt2^jT9Hyq_xIzU+#VZqcP zj-fz+*cxmNvIM;IsZvkP8C&!)mv&-%78!v4z!V)ha&$NX0`u4cMUca0jcg|*n@fIis#JRb-@5|P! z47wb>Qe_b9RarU%Y1HZS?Nv}?2`edPthzf!tN2tn#saLv>zWxb0XH?iFfmMZ=AkaC zsvjC^0UQFbA8db7Rd4eT3?K^gu2lxCQFc!0dtTP< rW8|SorSR!$W7~%oyV=cJlIB#t5;OP`e?a?1VfK@s zOw5c7jEfsT7&N{$kOu~%tTKy)fmnlx$Fq!|+Lty>z3zTPSwX5 zp2gU}&_I8I?gH&L&5V+g0xNy}wAp}ZlbwlCOc!KUG0?E`@^Vzeic*X7ON)|Ii}j0A3-XII zOY(~@=vAxDeXBDC@MD;G7p8X^V5~cL-l`|JNNAQ~YP$O=%-Zi`COjL{?3^^m?(32#4pk x-A^aJZ#H`^8`Wf#MKegBk0RWzELH+;$ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d b/external/boringssl/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d new file mode 100644 index 0000000000000000000000000000000000000000..677607b72b66a65bbf974575b1c5e3794a83d77e GIT binary patch literal 671 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&e2?c8#|hO)MY@xIsXpLV#NKEdZJUG$MOHOCVq5$!G&!HcqWJ zkGAi;jEvl@3mwSGGdQPf>XI`?Qs(~^{kXcyf zO@2Pm+-p=f7j9WeYEfQliGpKkNk)EAW=W-jyODvMIIp3pp@ETwp@pfLu|*V+Yi3|* zWM%*cQ3jb7UP)qRoo2S z6JxeP6Jxr8EYKaYsw^PSb7-?Q>}6zSWoHIjrp?C4x{RHf$v_9BKu`r3!%Z+J0wcH< M7{SjV35Qt-02bb}Bme*a literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/88e90e49acd2ab796a48eda68f66529dd4206671 b/external/boringssl/fuzz/cert_corpus/88e90e49acd2ab796a48eda68f66529dd4206671 new file mode 100644 index 0000000000000000000000000000000000000000..7a3dfe474ac14cb1f9175c51cab3b80e43261909 GIT binary patch literal 64 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5MuRk}y-o0!L;hMn)zkj)07BHB1IgOsbRlpBnJ9 Uaqj;1S%*;~=%S>+gJuKfj0MahA`OO)BTMNqJO-UJ6-2@HOeoPui)pr zp8X8fDo16_H~6T1p89R4!=l+1j~kM*U$<1Bf3t|os7*=#P3+~p)ftPM7_$wU7}E`8 zfmX|^vVi={q0Pp~%F50RvwXv6phOl|TRB_#z``uYXgnMnHe-8~)Mjr5X>N+61@7z{uT zGGK(OPtM6q%_}K3MAnp_TwDP01|N$Ui^yTKXI+zX81=N{1Ec+}FAz)*Sbf!i2jnne zM#ldvOa=@F@*tiv3ozUpM7-{@iAnGIma(<$YvZ=vNm9F_8ubknK?)RDqzoj0I=O&> z!NO>Gt&)kA(SU=EExnNk7`+AtAT{zVng;3ystc4CD8k){!%sO#DV~*)n}NBBk&z+Q z;@rH2e#;{hd^Y~u`AR)t*Yo?55BGncv(upMuY8^^Bb$Cu=Ao0uZ&lxL8!T5VoqzXm zmWg1H-@m;7pQCD}+wO1L-KKJ~bDG2zQNd!9f}-08nY|RYX2~@=C@hj(c;JS0rR=SU z1D73c{^@$*=Jj59>H4dNwG|g;Xx1d()cNqW`-RFg!Gntq#J?0X6#TkintW#W(iUft zZyRg%6sMldi=DY=1>uu-PiHfy2M#>iwTwTO#jd0s~c{BGh4GG@--`Rz7~e& zYnaYtJOu()jlclMQ6LCYt3VKDYKNCSxC(^W{O`Na3Iw3LKzSXQqo+VhDhY#kAlEX( zva~@1u(;58Yp@7dTr{DS7LLGB0F@R2kX#SSMI`3>9jMvfVe02^I~UE?7}#tNF7_}Y z%m7w`Q!&C2l?Ap4y8tYw4H_62fCSc}91(M{h{IMEyYhh_-T4IHvu7Ng4gj-kzDxwgqo?Kd#s^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhSIVPI}z-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5?A3TJ!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9rE>ziNtbL0N~`xL@5Q_JD*;sLoU_2(MT^c)342?H^(yLk9>6Ek!4(!q|? zOU}z3;CZx(SGwJGVpiM_nHI%9DYW41vPW4eJX z&}vy#7LbEEwAmP0S=pI^RzX=z1|V5M7GTIVfgNX!a9oo>W?oW$1+sIwL8|##SeTjE z8w@gFrZ6(H#2BbY8EC@<44B&FGfGMdtn~E@vNJ&jJkCi4`B&fF)6v~XFS)1$Niic_ zadJ*(YFfVv9;`Lfq4Scx%wa(r~_sIb#8{h)9FsBw?nE1&+Y12UIH&knydC z378jEC-XlwYK{{y-~)OLn7P?q3rjQ85-SXKf$0S(!Y!-< z6;TLQPcAJ=Rd7x%D#=XCOinCGMPzbN4mU6|Ff}qXFnOgOu6^n)@F zoiu){`i9?NxmxM`yN9z(1cQ|Q{^kAG_#9O$-3BTFK;?mjfrXLbQ4=uNzzNlLkgN}M z9j|+8en?SiafyPbR{fcKrc4OQW5KfPnvc`3U$UgU>}sOilEZi}mnPE6c? aGF1EQh3UWuv74ioa^^m`Yy%aq=b8Z_)~F@` literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431 b/external/boringssl/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431 new file mode 100644 index 0000000000000000000000000000000000000000..4ce4a75c88bb66249d6478c42fc4736f6d981bcb GIT binary patch literal 71 zcmXqDFlb=Xd27(b($K`5v4B}bq``2KFjK|?M`k9*MkXeXfQ)Z7Oa@I%s+0Mj8fqCd a7&NePa_s*;XXi5wElnE+AZRdbSPKBsF%<#; literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/8b188b379875299b1f6ca0501cf758b3a313a7d8 b/external/boringssl/fuzz/cert_corpus/8b188b379875299b1f6ca0501cf758b3a313a7d8 new file mode 100644 index 0000000000000000000000000000000000000000..fd6a3f4f588c8a06146472423876e638ba838034 GIT binary patch literal 61 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5MuRk}y-o0!L;hMn)zk4#SLZHB1IgOsbRlpBnJ0 Raqj;USYN!hPks?Wb!#AVc`r2i)N^4{u<#Z8Ra22G6V2C_h_WmQ=~4(8Bi zV`ODzXJ&-6m<)74(t<3&pld>RU6Vj&UQ&JqvU|Bfs`*)1n3>oc3^HKGFfy{l7(^*( z!}tbFZSolWbR zBE}+e*z8%?%H*O^;ZpRD=y5?tVzD9^Wkgv z3zcVr2NxZPe<@}t_;tZF`ONO6EzTm}HrDDXPCc0yJ9Ezp#^t`-I;^g`uj8$CiL>Mu z6DsAI{-4KJH+&u|+mT?K=mL|z3widR=CtnmH&Mhle~(+hB+ly8rK>I)q1l!qCFh%-A9d$Tc%CG%_;)gD8VcB&!7BRylKU@g(MCrsWsqWhNSm z8Hj+aV&~!Y%`eR>NzBYs2+K?@hq)`Chs&Ld5#%mUpt~dt#K7+2;m=LX%+X5+yI3zd zKi44AK$wjk=*@GsOpI(CUmRb&J45)%3?Cm0Z9w80E4ax-E~a@nR!Y170B-82C3#}VPR%sZ!pM! z8NFXC{XCmp>clUI3H_}TkDnU}r2vK}pUq3k~Gc~WI z*brGqesXaE#1DKdVk{zu&7O5l&SBKkjt`9XyS_j$Jz(`!10Im8gc%wCvoIMj7|4To z$}GS@ZxHdi%O)nh=Uc|svagNXb|*>gifYt1Py{JZV39JA0P5rdh6D@awMr&dMgtBu zw)93GU@9~)04b4Y(KJvuP+g$BK#`Dta?p}1a}y&YL#o9&gC>>+gC^z-XyP`^_*SDj zng1!8YJ!Oyl!!=9+~%eRMn)KkI|C_kBk~ak50^91iJJ?UxFMMifaW^q4A$ydOl>rzm{0u;GE+$a;Z1L)tsZ+w3b;V1(YnzhE!|f9fB`akJ z+kY_(KRfZp$t_#IluK4ArgwbVYg z%O-_PcyzJknB3BHc1HdzJJT;did-yRdox3H(}xL5mKuoJ#b@1Q7rEHRI>+Kcaq5#R zUQ;$te!7WGS>(#+=jTngyS{nJe)qwi)6vQuR&srHOux1_>-Eoy`5GYb>4WX;tLrr- zH(S;lW}e=&+$^Mh!2zw%%M-)xrZ>-c>~59X{laL5^Vx$NyO)Q`74tRfZ;74r@ZkC7 zdifg+5@HjVGi~3K{gQVFL&d52zY2QgKWZ=eu#Bnbi?Zp13K>aTCT2zkMqozu1_p^c zp^VyK(7>ee7LlMtL>dey2{UCZa0C{dppp}mxR?x@3?xBmSCB=>K%faZN&bzXXC$}uhau}J-;vc@UMKHE+dM@Ea^wE1iG$a296P29^Uv xWbLV^WWN5k)Ho?qd&!2cHG{EkMzs&#tjz?=O8dXhfo5|P!63hXc}SW4KLDMeP$^1|8g>fi6jJbr7Jp&74VLV~%jvU73rUphvurM}*1#$**Aj7SK1af8? zD3B9L3uJKvQAi;3m6w;p!uWYRFp!%Vm5@Ek$jZRn#K_M86z5W8YGPz$*y7bOQ>TP6 z>x!3n*ES`ShubF}N><7cw*O)nesacFlzupx~mrV+p@aSU6F}bDZ?2P<1Sazmgd=$C3ul8n!=%x=7mMk?8 zvy0EV$u4rSjdhO2gW}XDSG=Zdp8RwZo3hB2&(F`BZg+k2lKt+3J*T6UJFMjT>X?3Q zZ`SLd74tPf;L``&*;m(VN^Z8SH_SY}XSrEO`+@^np_eCy+f8qt@z~uewflw94Ck{4 zH+C-%l`H0J)ZY?2=i$Ng%k}a%7$n3dE@#@lC;KJu4u*ug;-Xc<# jh)Bb}1%{J^nKBkQ0<$tOFJ~BXe5+wXHvyK-IkZ^-Y#%!6 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00 b/external/boringssl/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00 new file mode 100644 index 0000000000000000000000000000000000000000..4e1df5dae765f85a345df750392d829a8a1b30e8 GIT binary patch literal 70 zcmXqLFlb=1d27(b(qPcUoUwqpK}5uGk}y-o0!L;h#zrP4j)07BHB3!Rs+0Mj8fh5- Zm9ueje4n%PnTD38&2a_>h6dAywE*J76`ueA literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/9070df87024c0167e6a1bd9512f698d3a31ca0b1 b/external/boringssl/fuzz/cert_corpus/9070df87024c0167e6a1bd9512f698d3a31ca0b1 new file mode 100644 index 0000000000000000000000000000000000000000..7d7b7927783255c7fe18cc84610791aa2b967526 GIT binary patch literal 2626 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%SJ zJZHNG;`uv+kTt;n5`fp+{@2$>Q+{Bn| z(8QQ-APbBfSydKLlyYdZF{-k%GXo<7$YKSum<)74(t<3&#MOize@z0Jc}e*d$T7+d zQq9l8!py|pV2}YbhLMpa#vsZ-8^$+aYLm|>DJihh*DuJr0-rwE&c3={Q*yIqy0>Siv)mII8K+?jDjQ?4f3>XaL zK|Ey^VB%>I@w&@4XXmpvG3hrb+_?kP>+oO#^iU)dk866ybq~qZZ3SE(L(iIA9^p$dGDr vZr(z_<&g>B`F+WUL^=c5`1>oLr_0EuAC!40*igWLkBu1s`qbsS literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/90fbdf2d500b38c15e3364d041484cf065cba9df b/external/boringssl/fuzz/cert_corpus/90fbdf2d500b38c15e3364d041484cf065cba9df new file mode 100644 index 0000000000000000000000000000000000000000..90a4e76681e6cd43970e1b8bbf8ac4ded8d7bc5b GIT binary patch literal 1060 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|PmRb z&J45)%3?Cm0Z9w80E4ax-E~a@nR!Y170B-82C3#}VPR%sZ!pM!8NFXC{XCmp>clUI3H_}TkDnU}r2v?k(lbM=VQf!E#hDssRtkRlvuGNq z8>lW&UZ4nfA`buLpe0x4CPqevREu--7WyrZOz_$GZ|5uZfL+h;OFsN7pQp>nrXQ4f z=%n#m)i?YG%hgKf-#wgVA{gZNFYmv`=crogw)>lQx2c@$oF;KaRIu2jpy>8NW-o=U zS#pgI3X3Ec9=Ks$DSIp8z-5Py9##@6XmIi|+=8Of*A|efjlZ2Tv v7B~X4J1D;gWPGb(0_K0!$^1{hnz~0N6lq^928HJS?{juO)6fD&0fPYmm%mBi literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a b/external/boringssl/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a new file mode 100644 index 0000000000000000000000000000000000000000..75117a524362c3af3dcd03ee2a00fd277b625639 GIT binary patch literal 998 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|Pc=&S@GjsIP!7kQI&d)W7G!SNE2YU0I zEfXUf2bjUk$j-?@p`GxWo{G8XbpP^disI2)0A2o-m zpTF%~G~42FLsItZmg@6w7I7K1De1q7y}Y+NV^I@hc9Vet)x%Z}PuM=d6}DEy1@13! z;HpCcHxwyw!^%@L4f7OWkxpXZ8Z;O*Fd>DoGdP4xBngIa6Jxr8EHLI|Rarps&7sZ4 z$jZvj42&rdYZ*H;lYtIMT2Mt3nDl_wa4;|!G(jTS036ASK(X8;keQd14|avdTZ5(w zz4TmAk_9IKZjgR{78YhE_6CCtm=%nSEHMUA2HG&b0aKfNMoCG5mA-yKb|z8+(s%cC zbT`sVE-FD%%m`PUoRgWFS5j<S@OZM*Ce~AebJo j`lqr*kWKBGe8ccCgu#xaAIX&z$^j)h%X4i literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad b/external/boringssl/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad new file mode 100644 index 0000000000000000000000000000000000000000..60705583811fe9d362e71a243b8f7750d5038833 GIT binary patch literal 771 zcmXqLFlb=Xcx%wa(r~_sIb#8{h)9FsBw>Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#Nm?Ta?j6C&q-DA%u6;@HBbf# zG7HPV1xr$k@={9_97{_w@{2M{Dit0W8OVwA8k!m!7+Dxvn3@?|M2Yhn8JZaw7=Q_b zD1%I_R&nrfWhLfhrsWsqWhNSm8Hj+aV&~!Y%`eR>NzBYs2+K?@hq+6Khl}et!eJ5y zVqk~y@aHCG=IEt^W%QEsa}6R5gxT1E{yb;P#K^`0W-v3dGdnS`NZ#4fB%bbXY!Ln9 zrQGQ{zpGJxp?n2D=k@Gos8%^DYrMfn&1vfAZ#x&wws_o-l>NG;`uv+kTt;n5`fp+{ z@2$>Q+{Bn|kk`bRZXgS^TUM0?!~m2kR=hP>#L@t?5S}WSG8Q-j69gzl1Y~@xVFEfN6%mV|C^RrK zFf}qXFabuK0Wb;;EetH+TmvV#%fP7x8e3e#yzZ&_Aw{LdC7|@8XDDqT334B^un=6_ zJtsdYF-O7K(V&S@3E9JptPIRejQk8haW1ANMn;BPXC#sh{$g>c>SX?>2K;QC`@hfG Tsi~o*X<+w7Tv;ltF8V$I8FrE>ziNtbL0N~`xL@5Q_JD*;sLu0?1Z0&5(Z*mck%G&CT8a7rGp)(mzRHyC8V zOkreXi7`-*GSG$z7%;WTXOxr_Sn2B*WM?87pzrSK=x(H!TvURjm=UfxIVUqUucX)z zs$-o&gFyq6!2dZS8`?Ci8-U@ZpPyV@0P#^Dix`W@VY6pllXDpLwBrN)t}hTw4_JNG zfCuD8VMfOPEKCLr2J#@DGK++P0Tq%NI64u@Oa@Ofdq7z-`?Us?%+w*tOsqk~>n@v& znDm}+8C%P~Hg4OUB(*E5QQtrjyYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krUqn;02xosmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZF1=nXBf{aiZTHiO t@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLI9#yL9YM+ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae b/external/boringssl/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae new file mode 100644 index 0000000000000000000000000000000000000000..5d40be852bbb587fe63445ade5842f1b094afa8e GIT binary patch literal 128 zcmXqLFlb=Xcx$kTrNN+yIb#8{h)9FMBw?nE1&+*2jEq7|903{MYM2a~m{ce8KQ*vo z>x literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 b/external/boringssl/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 new file mode 100644 index 0000000000..034fc2bbd5 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 @@ -0,0 +1 @@ +¿ÿœ)†(; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd b/external/boringssl/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd new file mode 100644 index 0000000000000000000000000000000000000000..7cd7165deab09a922bfee1fd72bea70c5006df64 GIT binary patch literal 262 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 z;&2Ibx##Dn`=l!5 dWFRNbYiMd{U}RxvVQOY<5hc#R(qO>b1OPkuKP~_O literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad b/external/boringssl/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad new file mode 100644 index 0000000000000000000000000000000000000000..d8d6fc10c9974a014be703a11bd59317f7a52905 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcLazb!%_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#kuY`F)|9=IwO&6@b`#y22&TjwCGG z@V?SMd}L9wafx&iMybsMU}*M52z zpM8m;cc;h?5mD2d2iz7{7oC{6|7584*$dO{=BTBdxqq%%vhbAOvnyAtS4y4@y?5fx zr8tY=r!oFLy8i-{&Hki4JKeX$Qj%f&R3^)b+&idwSm(R~GyIx1GKf&_R zFSB4_%PVne+P7_2i0n0bEy1i2#8UWlwXy9(i{0#IElG1KUx^ufi9ewIqA>f(PbOwY z2FAsW9}F7b8ps2KQC68n!a%G+#N%1UPwh*are1fyp{yX_Z#-kd{3`~sAO(CZVk{yD zs%B*LcK%+?n!+PkyQ(&I$Eh=Z2K*ptVMfOPEUX61Knk2bWcfh?EWkv?W?%(UAkSiK zU}&JfKzD(5n`TByNr9EVesWQcUV3VN2`EzalJj#x0>%2p;KY-hs0ZX3_<{5)u(%tz z8aT7D0GSL1)&`br9NKKaw8_rID5eWCs~Bild3iaiVMVFM`K3k4sm1z5sRjAPnI-u} zmB@(#n6{Z48yU(T3g!8EiwU)vvTbVQIRAm;`0>KJw0DQzUa^+{|KY<4ziZAG8+IDh zN?ZtSUX*p(OmNN%kF>?P^*e;Gxc}>piYflH?xwVnq{Zs#CL*h*S-oB?Bf{aiZTHiO t@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLI7bYLDT>M literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db b/external/boringssl/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db new file mode 100644 index 0000000000000000000000000000000000000000..1552adb572bca7ace0d5d669f5f4b6598d4cd578 GIT binary patch literal 144 zcmXqLFlb=Xcx%wa(r~_sIb#8{h)9FsBw>Rl=4%E(qSl~^>DdBiCPpSEW})5B40zc% z+dSH|zVk9Nva&K5_!)8=aI!Invaks=g$5f681R8OT*B@EodF*asb7G@s)+{DZry>zgP^^)^*4I&MM z+1P>JJZHb$(Z){6hH(e$MOJ&rq#$ zRMvchkD9~O&);?~nr-p8Au0QHOZE9Ti@1#1l=R=kUfx@svABsb+n|Xt-9Q!?B(kb3 zAO~}3voW%=vNHp%g0h$lbU@OAEWn^^LU&!0KxST2eg(37xk0M=Sy-5v*c%KoV8$>q zvcwofDQLs^225@886_nJR{Ht{*_lZC_1!%k-Hr5;i%JX-iW%XGlXEgt^Gb>hk#*!J z7Z*VMz{euSB68U5S=ZzoMm_ELz-Yhg3k1^xR$n#X0l7+;k?}tZlL3Q)Jcy^v0u1y9 z5wE*!V$yrQWmJ`YZQQmyNorSAqrQP6NPz;2lz{|LCl@dzSQxKWGO;omaImqZH}U{e zp@9KNi9Cy@fx3a}0_6pYa3>aIV)aiBT5@G>Vq|1UwKz9#q2Kbz1fPxncD_;%*!BFr zeeZz0CT&;Be-NRWXfu55SbwWgoy@P*)Ufug0WULKhQST%O4(Zx2QE9@{L}Tq&Fj7J()CvjYb!3y(5y+m zsq^7$_Y0M0f(I8Jh<_<&DEM{3H2KW#r7g}P-!|6jDNa3^7dvy$3dZHW+d8bSy07D{ zb&0d&785Gvnf{;0S2uhfE8CG^o9F_Qz6*KwpXRjg`ZrO;H-C>?z$DJ<)TfyXgx=4e t?jzhdQ}VlX9gjwwQl6mvo|Rv$9`U4_Z8g;?NO$A@YU&=9P^5ja7y#siMFIc- literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079 b/external/boringssl/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079 new file mode 100644 index 0000000000000000000000000000000000000000..901fe6ffa0a58578509d99cca9a29ac2111627f0 GIT binary patch literal 1096 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQWbe~j(oV;X1RRd*^AhWOxNH8Z=!85NUwJ0yOM8UDNBqP5l zv!qhN-N-;roY&CQ(7?#T(8AQr*dhwZH8U_YGBW^!D1%I_R&nrfIVa|1rsWsqWhNSm z8HfO_y1>rE>ziNtbL0N~`xL@5Q_JD*;sLoU^=F=EdX9pjgn<~?T|E4`iJ3Wi>0rm{ zCFkcFL>dUQu>-w%&X$RhjRVYJW@Kk}VqlTHv!zKq-QUc#0@=CTAl3XVEX+*o z4F(x7Qy3XpVhq%y476ba225@886_nJR{Ht{*_lWN=(~G5x*O>w7nL9>W`rwF&dE&8 zD=9XF>R4ycV9>xM@PCfThBgiB24HyU=O-5zKz!84BE}+e*lco67o*-Y?f5{y>k9OnT3^jICu~8@KIFlG+v3sBfSM@|*&Tlz{}$*Id9TWnsKl$;8TNz`@3r-pB*Y zP6pukm1og3PzML5##@6XmWK09%oz)qMMN45CkZoUEN}$oJfK>MfQ)Z7Ou($DI+_2e zAwQde>H_5jitxz65tBLKj0(!9oZyVg+{DPpkZN&m-a^0SkqJH<|LuIG9c!tAbvrI~4o6^6P7+8}9e0~OcO!psI?g9e}|mqKuAa%oYjf^%w7NoHDR za$-rUf@5h(Mt)IdNu`0DIIn?`fvJ(9fr$YSM2YjNTNqftxdu*POWDDeh6Wpo8Hj+a z;1cF_Pt6Z0DlINi@XSlrGn6)v1c@^X3&F+RbMliCa}=B%4VoC0kp05Q%D~*j$j<;2 z=h9?qVq|2vbw(oD;O`f4WvQ^b==(M~7EcPdS4_OJXWA1j=}=B}OLHc8L_ z)W>$`gJM&|bpzga>NZq`ul@8cKKl|w?@o~)BBG`@54bI^E;=!B|H)A8vlph@%~4A^ zbN^hkWZ@~lXIHLPuarC+dhf)WOK}##PhW))q{0#U((!z|4|5;cK zn1K{1nS{#ng9KQBX^YLk3dEOZF*YzX&|jdtK)X#dqokz3N?$*@C`T_nHNONDt$NA% zxgddJ{bF$PNlw%Q@(lbI7%(w37#M(zP&mTkZs2O*%*Fy_GZldXKe%@k2Z3b+c zI!-Vc$gni*|K7mRu%U^i!JvsbW6n-UR?*}zG{~_2_J7WXHjSD_j`JTljvp_qOS5ix zcgO&y&swYL?G?JX@JL&nTfam2iu=FrsF>nE z>uyRLNm{I)ZX&X3+NIZvWkfhUx9xs9@qM$|YuT`T=8P2PQ@8dMCr@}%U#&WsU#qEM Z?OOvorPH?TZ{sUU<~(NR4e(pI9sq*qT3-MF literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/9baa5f344ecd37e2762cb8a7497709b78d69cae6 b/external/boringssl/fuzz/cert_corpus/9baa5f344ecd37e2762cb8a7497709b78d69cae6 new file mode 100644 index 0000000000000000000000000000000000000000..b1f09056caad1bde7a4e7a25c4a18e961b608b9e GIT binary patch literal 64 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRk}y-oE=Oi2W=19^j)07BHB1IgOsbRlpBwPA Uaqj;1S%*?Y=2+K?@hdYc5>@XiCpv#gCB@D#C4&&j^P0Y;EO9wkyFF8NgAksjX zjUDLEbGA&3>>OYQGb1~*69bFnoh?n`>HfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}sI z8+_CprhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&xd{SwJr4 z&}L&~Wo2h(WaH3#17R{5=z!z}S%87pgzmg1fy}(5{0fMJlT-B!*z$9^fvWjgSeTjE z8w@gFCNe6r#27>wXv6phOl|TRB_#z``uYW#*-#JXCFd{IclUI3H_|IAK~l>ISDT!Z znVMHpY={UUgC^!$VCr}VNgd2$yPqK^3|3&m@Po&eFeqUN81R9DnoF47wXifQEwRE- z7ibkwgj-kzD3S>jQ3y^=E-gw`_@7!-l9`s7oLG_yOdwNBSRqLSls*iM3`~s-4NO2O z0+c>13@qSW11A(4ji5<^OPJR^H9w@Nw73M681)RL4J1MKG7AgA#DSh6EvbWj1WW3| z*pj+1YEnl@>4uiXr*veSIC!w7bRKX@S8&hCPfE;DaCQWyEhXf*U}R-rZerwT0E%-l zH8CN e=YQ&ByYoS@so}Z-?>luHs>0WPdS{b;i2(qDWG=e^ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd b/external/boringssl/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd new file mode 100644 index 0000000000000000000000000000000000000000..41b10c203c12fd051cc3ee4ddd137e1d39eb94c0 GIT binary patch literal 1004 zcmcIj%TE(Q81K$3+wEg1xCAs2Tm%e)(r*^QhQvf9q-~<8AvK}sp)}j>rmzdmHeyiI zY|I{vCm$z`A@~n)@Is7m@?c2xVD#jTNMh6z3Fyt4ZOiN6%{k5N&io$V_xqp>Wz_u( z9KH-rhrWoPHkHX^8R?6|7#w^L9JINJQ5{0~$eT@&gg}q$CUzu_tE=lEUfX@>nGk%f6tF`fgK^8sPiqQP1urqdmAZx9gzYdbGiHoJqTf%t$ElV+B5K?gH}<>OTyNz>Mfre-U{C0n6Hz3h(LKAV;Cu^B<1PWQ^&)yw{ArtTh7@APasYU)Wv68+bc`YhhiJ$slty33m<gW)*-CZy>cRAB+RCv+Mb7FI_jyUDAB$hK#PqS4ucu@5*JPY%b`zHHI1j44aK amu>dgi!93>s4$=sIOmOM!exOwl=Z)cnf)jL literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 b/external/boringssl/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 new file mode 100644 index 0000000000..5fbfacb11f --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 @@ -0,0 +1 @@ +¿†¹ÿœ(; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3 b/external/boringssl/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3 new file mode 100644 index 0000000000000000000000000000000000000000..a2ab64c5a0d453c6ba32752d3211fb5e9948daa6 GIT binary patch literal 195 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 z V3=ECT48S1DAQRIrps^eV{{fFgEwBIp literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff b/external/boringssl/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff new file mode 100644 index 0000000000000000000000000000000000000000..4a375c3385edcc49b62fe9ba0fd170587390dca2 GIT binary patch literal 1082 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z&_GU{*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?+|g|l$*a5*RDWTxd83?m~; zj6sxvHjHn;)Fz)%Qc_^0uV0XziKJiO-P6(CNH4jl1W7R?Tyb(vW@=tZu_3aK{N&;S zh#&Y^#8^ZQn?38AoWrQ69UmC&cYT3idcf+d20S2F2{SVOXJIm6FpvlFlvyOK4a6Em zyza7zN$>fVv9;`LeI{xLht8K g_YrQKDfwNxjz=R-DNj&-j{%l!tVzRcY-At@01~uGH2?qr literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420 b/external/boringssl/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420 new file mode 100644 index 0000000000000000000000000000000000000000..09c2b624a2a4daf846560b51bcf5fc6b33e97116 GIT binary patch literal 1088 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG`83-;k{eXW`)Ca!$<2Ov^9I%S<#B zGZ0~8wq{}H;q}cg%_~XF%u@)naNu53;)?48+)&OIVnB_%m~I6ZO);F4jxV z&oziN5N2c7YTJ6wmWh##1L)s#w#S@OZM*Ce~AebJo`lXaLK|Ey^V4ydMc->_aliu?!V{6&h#%;Tkq;^F$>KiD66ezGr8At$iasfkvh4ES? z6Dy+u2OC>@BM&eY8W@0-$g^k~s2iv*P+p)2cOnk|eeZz0CT&;Be-NRWXfEfxY|WBubWm6%x$wXZ>q^;M5eF_i-2Bt^!p-Zw z@Y3~H4Qned%+Rb!zNz!!YxfJ4XMzV89f*G^W+?b|!8G~I?xiixBHuRF>M2e=nHM{A z&kDxnzS}yiuDY+|t#ygBxtu~Lg z@4SqR+^h@+o`&28oNUaYENsF|p}~g227(|CmoS%metvpRs)A=;vZ1PhGDwhFSOzXw zl3J9PTB6`sT9T1plvz@#;BI6fC(dhVYG`0&VQ67$W^54!HCV}s})FXc|x`CX0j z3*{^LIj?6wL$%6LS@R7(Y7SFBf7`iew#DOyr0mx%)#u+V;xcMe(ti_sd2h7=13Z99 zjVKK*O$H#ySlq;zZP3J+ZXgSEysRn<$jcnsY>cd|?94#NLRn1CIv{C57GU5v@#muY zuSp;?FDbtQ*~i=<)%+|h%uMVJ1{pA87#Ue&45F+Iv>^iQ225@886_nJR{Ht{*_lZC z_1!%k-Hr5;i%MW>S=kL3;fj-UGE?(PiVcx<WbRBE}+e+U!}^{Q5Xu!e7mfpw%Ov(lZASLoFng;3ystc4CD8gNd z!%I16X`Z=>k&z+Q;@rH2e#;{hd^Y~u`AR)t*Yo?55C6*N=`ynE2W1{QY5Z384Zp#1 zwbJ=(?;g%F5e)MCm-qj3RIPN|{Y|^uR8DqIlei)(SZq=N&T<;K@-8D&(d~oGUJ6^Y ztVyH>@jVZ$%uq>~Ql>*9$kV_rj`6*IzZPt++5lvnKhb&WEqvFI1ih z9$a)F{-v0qK@+fK2%&n0egn)i%o>mar$GRmq!Hx~1E}B;{JLP8d}jC37H5%f8*B9x zr=HA7mU4 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029 b/external/boringssl/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029 new file mode 100644 index 0000000000000000000000000000000000000000..b12aa104b6f3275e32abc6a6997fdb77de9e19e0 GIT binary patch literal 1869 zcmb7_e^69a6vyAM{oyV@grx;kWEDYhg*|V9ZIN_RMpsK0l+XlIm-WFuS@*HO1SFVc zu}w=WYM7WpL~+t`oX9B+e}t)x;O`93EORU+e}GaNY9(~vBDhpDP4Ay~?|J9m^L^)h z?z!M5%fL-^){_KI5M=QFPVg6wnB4+HmBX8m}4;}(4!%o zx0ABqA-m4ZV2wCUi+$NT;aF2G1P9*7~kB#v<7ICk-5m=PY`3ym7JusrATGiL2o z>)zt3wgX!(%zdyUZ4Y^4-Z+tX-NhGGc`0!R1;wv#(q0$rU0H73)_HXK2aR`JSJ%e| z)x{7EkWIU4X1$$|e*BkL)4r5fFN)8&vp(LnX3?%+Z!ar2hiz;M zc@Xkc^0$X(HI&*~s+wD~l&8+VJFPZm#mUR3E5ohF^_^|)r5}c$%KD+D>)cXp=Cvj1 z8{+#iqBMWzb)I-*TS_>#x0*<)k_Pl?6TXfRyw^K#8W$*v_;~WzH;9U%wRx5CKS1(fyL&cvx#wEIPxwYjw=H{}^{Z`mQ`b!)-ZhXjdZctb@GRCGfm zN@PS76$Wxw$m~wjL*=>M)#r5=q7)<36Kmeu+y)W6LjWbGLe|unHm?6;r(lI&P}xUi z%;(2X>LHN-D#P)9N&qB!@t9;q1o8$7u_c5l{5+CM1R7NJ@%2hioXO!RoT5@0ZRUi0 zhI8;$O)zq+c!OPK_tIlDB%m4S>w&;r0Q?q;qm&M2LYk05V+_Deb|8Si7ywvY&`iw_ zSlpW9TX^X!7|a=>7zo6Z41&;Jh$o4T)&Q;6@ZchnfgK7Z^9d#PlcX8UY#wK`u!cdNMSlMCIH$#7U@eM; zEK@X~tDTbg`RYO?@#^vmTxDQUuDpu*Ou=H12}S6zo}NnJbwaUsMB*ZH21bQ{|EW7P zKRpq09^4pvqFmpet3r=SGoGMaHa|yyzCI{FV`n?~@m2Ts1_H2Qjpn&aLiy+ey{6Ar|5mYQf9|M# z*%c}n$Ga=2Q4oe!N)U4t-cdpba1aZH`4xWXo*L)`kyIQ^gy{OH`f)=9AYM9rm}#s8blfhv$1P2K_oz-W0>)+h6xy2s%;+U zY?&C@IDkQP&X$>xo!NHCV}s})FXc|x`CX0j3*{^LIj?6wL$%6LS@R7( zY7SFBf7`iew#DOyr0mx%)#u+V;xcMe(ti_sd2e;b;wHvygC@pw16iPRWmQ=~p5)MG zV`ODzX9ijYWic7(fTRUkfT7(4^-=z0{-?kQrNcbK#+}O? zY9Pzc!otkN-e8acGmnvxB?cJi+AzKWQ=5E7NlAf~zJ5V=CPII%zPqQRyOCaUQ3*mZ zQh-e6H(-S8OwP$n%_}K3MAn|4TwDP086S%ni^yTKXI+zX81=N{1Ec+}FAz)*Sbf!i z2jnwhM#ldvOa=@F@*tiv3o!Z`M7-{@&5>@~DfVp7w~Vc2UmLgWPLkRc)u?Zv2vVfL zB4r=})XfD9BNoPMl}xOR1{`c`>5V+VNHZ|d;xGcKl4sF0P&ZIzV1b6!oSg;>lou$% zU5(`5XKh*>1`NP(WYKES*OGyGJqImUFgGzUGNf9Zo43$!d1Qjm#(z6ssR!(OeqZw8 LU->*;MmBu_%GvR1 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a37c3ee4668153e5ef9c272d43a2545a75b36854 b/external/boringssl/fuzz/cert_corpus/a37c3ee4668153e5ef9c272d43a2545a75b36854 new file mode 100644 index 0000000000000000000000000000000000000000..61ea85a36483e8e32d17cf74d4997eb4eab87cf5 GIT binary patch literal 939 zcmZvbO-vI(6vsQW(`_j&g|sP%0!6G8FzwqCYSoyC9x4VAVlbg-3^cX7>Blx@F%pbf zHl_#TN#aRkHkf$vqKO{?l^%=-V71O;N+W^?+_cpji`{Wt9{;2j zi}U&^DdFGHWjAyg65>J~cnn>3XJ$l72a<-kKpZxKPzW19u&8%a77T`*fgy1577F6^ zL5z5-vEYz}J8UA`R^C6*YLh2AVHp4V+W6{H-(sw9uqyZa*43hEa@UK7z4v-|AG-c$ zZFc5HzqocW@>v~CeY=bnR%dLX!p`98nYYg-#oHQ6frgUMKqWT#2s38u;E~yE;b_Cs z3d0_DTtg^gt>hxZ5C`INMyr;xqw<9fUsQD^%XSjNwPA}2qESbjqqaC^i>bkM=AbqE zrk!8F$yXGA-ke?bx3>YNkrf)D{ShLkp*02_>oNcr_L%@RiHefj9}MPF(q_;5!Dvr+ zG!%&Em9h&53hT-7w3NsyW5VW*Oi+%G<^KDwA|B#?9$vmOokoFHypoyKe5ISDfee478+5U7*e0cuH)T1Y(^>eYQAT+ZCFR6z*T8B|3 zezY`!%?PYKpPaH&7yvA%iL^m$S@nf2-b2}O`Tv6{SB&dgOH4~Z!PmakgDR2Nj4X%V QqBoZS855vLKN>^$2Znw9M*si- literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a46eda9b97888af5263bc32293f940a8c2125ac3 b/external/boringssl/fuzz/cert_corpus/a46eda9b97888af5263bc32293f940a8c2125ac3 new file mode 100644 index 0000000000..b951711526 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/a46eda9b97888af5263bc32293f940a8c2125ac3 @@ -0,0 +1 @@ +0€0€(í0‚€0Šh €1’h APhö|0‚%“å0 ¿÷œ¹æ(*)03€0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 b/external/boringssl/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 new file mode 100644 index 0000000000..be16f72a1a --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 @@ -0,0 +1 @@ +?ÿœ',; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 b/external/boringssl/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 new file mode 100644 index 0000000000..ea357ce00a --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 @@ -0,0 +1 @@ +0€0€û€&0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a b/external/boringssl/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a new file mode 100644 index 0000000000000000000000000000000000000000..523423a9ca381f4e863758d2e7ce678ab2fb6bd4 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9vVFydVg@1*`*__`^FxYCi%S$d^OE%p zr41xO;>^NAaB=sX{G`Mj1!qTtCPpP>Z!n57FgG#sGXTZ8n3@@NH+NUMO;}b ztS8RpDzt zy^GJj#L&A_CFRfi>r%HOx%AmRQv3O>2`C}QqJ5z*DP6h%J12gtJNzd&xYPR z@#a#TMex%Y{~q0c0m^27(w?2}TVg56uzf0%(8XO~^CBiEl` z`RJEfu(0KoI5q9twkt&T8oica)(B!Le7f4$_MydYcC(hGIhC)(48Fu4(0);v{p2ST zBQpcz;>HgKjc*O)fx#%N%pzeR)*#~XEaRv4rAyWdb&5b!siF=74{16hy)J{B<+ zkpopTGI~3IuVzi*5v*NRo4VuF89xJlkhCx(<9`-b17;uvP9L)TAORL&qGB_!0x6JZ zF*YzX&|jdtK)X#dqokz3N?$*@C`T_nHNONDsd~xzxgddJ{bF$9Nlw%Q@(lbydKFmQ z4O|VJ*;s%~1_NsYOEwN|HelLhXJQo71({V0G_1V59M!O*)Z+ZoqU6+K{i4)@{Nl`# z{Gv+aM8OJ76pf7xWeq>HFBK)z;XO|VO`q0LvOEG%m4rI;e_8cXNwIx z4QeGWgf=hAI&CI6=Y>bw;@tWj!dKk?bw|Y%|5h=FRnx3qFP0JE@Z7fh v>BRTVX0K(#@=x8`Q=B~ENqx1Q(rH`vxA7Jwa~?AX_$^#N<6YvX7JDH8n07%Y literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a6447b7b3c50340aa14feb960245856ddeebc2cf b/external/boringssl/fuzz/cert_corpus/a6447b7b3c50340aa14feb960245856ddeebc2cf new file mode 100644 index 0000000000000000000000000000000000000000..61afa88159d3c58da413fa2dcae2ba1f4d3f2dd9 GIT binary patch literal 1219 zcmXqLVrejFV$N8=%*4pV#9^56twwb+|5F2AHcqWJkGAi;jEvl@3mwSGGdQPf>XI`?Qs(~^{kXcv;E?AOUl$Tnf;8 zWFRNbYiMd{U}RxvZfam;6b0m(85kOw8Gu2QK?YW3WR+ri z$Cu4^XH)cfPwoG%z$49kTiwp>RulifM#ol%b$kBxu2{NkQpkiy7fX)GEj?#vs*v`JXUQ=?jWxZkM={?KMLfRJ`&^$W5yVX+9*qVMkM=x(H!TvURjm=UfxIVUqUucX)z zSx0_yaRJ0Ld@N!tB2!PveEn^yaZ;xCk_}&L24mffY99k0kQ;>=8UM2|888^ggLuj; z5(Z)oB3^fyU^!&}_c?50(tEyTY%TlRxNUcm)UK#TeFH_1Vg(i{0|}rhT)=>0VZ2t! z#L8&E!N!)}$O8-s0|Sr}c@|9rbpzD}$_o@B&fWQ}O^c%qw-0j=i4~qRfeDt8!7N;1 z{r!q2@BPg)7};(g`*>hS?&h9d7N6a&aqCsZF*=>noM0ZvYQy+q^N$x!6S-9dr^J5U z^ZN1!^UB2sn16njyP3FLYhk0%ZB2c{cRdZ89xsS_!aRMl;S?9;-(DV%EFbbpZ}Uvc zt=9dWIhR2vspf9X*^fR8OwWd!33&<_+toi0UGsI}55AXY1OG^={&Vcfmpb^P;OB=& zTQoMly6O2dPVRA_Z(w8|zuH8dWtrypXRMfd*KW_>S?~O>>@jo@)OmhU-|U%M_4;S| zj`O~#+j8#^{F2Ve@!sJc&)R>DsoT7C?=e*rJ0I6!lh|DPH{|a3ld@}bHmxcMtA0Gc J?{Qo5GXPP0sQ3T? literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d b/external/boringssl/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d new file mode 100644 index 0000000000000000000000000000000000000000..f1505650583505401dfef6fcb138fd29e16b493d GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxB5cgU?x9?~=Th@Sib{)16g=~i z^$evABtf<^3k$i!#NBi9lM-_joE;6C7?qH{!N|(M+{DPw02Jq9YGSx0!N_Bny6F2hITlX}w^vNOvS;B9pC2onw=uu;Rb=PrxD}zFW~sTCwW52j#S7N$S#^a= zo*hY8w&8ullTHo(d8*gmHh*5bY~t}5C!HirMdq%Z;WkOn|J28J=YwKX!*v7Rcj`7& zg|GeeE~SiKQgN_Nh#k6S?{RS?FDqWu5iS*Djx*U3R^W zTz`V)qhDsh!j@O!)U1t!!hZeip&03P?RK5~3_!56W`$b{) zlb=k?#~2tFH-0c^d}|;N3`SXH76}8f1`&^E89%izZJK)B{f4rFfWPsK3G=TQ$buB` zv52vV9H^R+(cAfZHERlwVC|~f)E%eJ_!;nnq=gw7|Ff_fFas%Y`jF)Z39tYY6`O$- zNP#?yv4Nq1{sP?v+HIN{B_#z``ufR5IeO`-`6Zx8)l1IL1ql@E7lRW|a-trPXW$3Y ztH9!J;A-H^#sXwA7+4!vvT4#7U!21C8rka7o`^D z7iX5_7gZuB3Sio1Zfs;IdnlCW=Pf4GX27mUaj^oD*>(bsGdV9rM{{M#$C;YBC zTWr{AP%CjEw0Tk1X*0n&FFeu~=hp8KzT*C`J1VC5&$^q^Mv@k*r<;hZns({+Vi^$* z&uzP(PJG{N_F6V9|J1EL#mN(%)K}Xnowj9v8*foE=P`4D-@^4X-X(r&u@?dWY)L}? literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a b/external/boringssl/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a new file mode 100644 index 0000000000000000000000000000000000000000..6b4280105403832f11c779f6942af3d555f62515 GIT binary patch literal 1254 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFp1Y@Awc9&O)w85y|^8X8!c3^d*vG_e>o z7&I_}Sq%bB%oz)qMMN45CkY$iFohS%6jlZUPeX14PB!LH7B*p~&|pJh13?gnOPI?& zzX50j+&HF;1yh0U0Xhh;p8WKjR0YqxWJ6U0WspJ4!ZPmp5W)8)sYQ9IB?^wEB^mie znI)A9?nVZ3;=G2Yh6Y9!h8Ct~#uiaPu9<Xjabsh%~mvdrHW?FtxUS^`9 zn1Kk$Ds~=T-~7_Nl0=O>g|N)ja=2f3fPMiw0TfOR3=AOWJvNju5Cc1phd(zlGe<8S z>_)xh{9J=b17S9HU^t(%WnyIG05O!A8QGbg7+56lY-tit_cu0({_#@obe-STD8Ep? zf}itx_A^wg9F;ZS;G^a+_4Bu#i)LF{JZ?zJe%(@i{>>sTqc$b|H?f!ZR%44OMQTJ; ze!5SpLJrnI&jTfcG%SgU_+$W!QX|YL&7)V8W`d*iGkTN~jLVG0O^g_!BMncI6uUp$ zpouZvKo*#kWK~%p*$0#wIkedrSy|bcfe8r8VlvPHDH3D>24WL>nrjls%uC9zKu(3+ zAl3XVEX+*o4F(x7V;C7(Vho}Tw4r=9W_AOnHu;Q_k^(Dz{etXFBop-AJssVR^pcB8 w;L6zz7=em0lD93PXFWC90;HatW)KtTcw43Ohs?gs^kzJY#nPNsG$011&l;{X5v literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb b/external/boringssl/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb new file mode 100644 index 0000000000000000000000000000000000000000..9529ae153f5efb0cae642b39d43624ccb788c296 GIT binary patch literal 996 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|6^CdTY00|TmutsI`PeLz{*{sM=sI>lj| ziW0O24F(NN7~xw&IDDHJ(+y;S@g}Rv0*Y-8Z8k<$R(57!Jb_rt*qNCObU@OADw@EA z2egKRfx(~&62%7KC|(3|NRvQjUQ#~T6&i01nkw|tb3q9f>_%>oets4fW+wIqgAAAz zjEpQX22lpuFunm(n|ww|Nr9EVenEC7Qu5Jv_jGhO(n~HXK~l^JSDc)anVMHpY>2EQ zKe@O7;wwHDF&2@-X3x4N=P>GN#|K9HU0)!W9NzBYs2+K?@hq$Yhg^LH-T@nUjY|O4K%sl+LiJ3Wi>0lS@CFkcF zL>dUQu>-w%&X$RhjRVYJW@Kk}VqlTHv!zKq-QUVK^9=pHKDt%Ngy*XDZc{Qz1$$x{46ZYOzaH?88BlQ z8ChZsq7<}Yd;_L7`HYg10xNy}g6vEr{rc{nj_yW!$wegw2*r$W#mPCDsd**EhR8bd zlZy)=e&AyfV-Y!Q_N;4i4x^rSd|#og}p@s!`uS5u`wYMan<|sFMpA5-g0@Dw$Xr4LI1?(i?ez zsnEaxq(q)Y(?H!ob%F8%MYt0SGO_w62Q9fWH!(6Yq*|Ptx6p5SWP;Dee>-2P2kd%& zU-IE!`8-`lHvOQ?Lnn>js=nbjSguw&|L)-|6Tu+Ae|i5uN7YKV-QTpkP32_gG>I#s zg2g5UMYj(!dns(ql2dPVP*^0n@PI*sLBj$Dh6V$JjuQ+9GAs@Izi((_X)tJF&X}_k zl8-bw3^T01)u>M9*J^55YrxCSmSJ$ix>EL5#DU8WH~)0KaPxXEymb9l!`g}qGc;?G zZ|Z#b+WkW1nc%@i2jX9f847+~Fik$QdufZa$hVEPdWus|=Ect3vx0HC@3s!BtM2P~ zYvU}r#e_a4~raA@bZdTl1P2HmsinK2l0|2ZdL`DDr literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457 b/external/boringssl/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457 new file mode 100644 index 0000000000000000000000000000000000000000..8ec9696cc06d2701b7febffb3249b32605a0286f GIT binary patch literal 1040 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyD6gcXG}TcdBfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG`834k%W+aPV+BC+1|PNzBYs2+K?@hq$Yhg^LH-T@nUjY|O4K%sl+LiJ3Wi>0lS@CFkcF zL>dUQu>-w%u9k_BjRVB6WoBe&c4A)Fpx zt#VY>e1ngg!_?2;b}pK2@wg!=`*ln8`8SKWjM|j+-^5FDbtQ*}dE#)%+|h%uMVJ1{pA8 z7#Ue&45AdYVSEFoHu;Q_k^(Dz{etXFB>npCo{sKDddWp41_;HBaK*_vnW=dt#fHc_ z@{@}TAb#Lu5n~ZKZ1${cat@=Oc6?y8-}ME8=>e;+8t{NzCCte9pM}YQ!9X6wQ)U4M zdV`49T{bc4J>N2_%Dy&k+npq}E2>f7KoO)sfknzd0;rP<7!oXu*D9G<84Wnt*wPz$ zfT_^H0Hj2oMbkjtKy`ug0!6qJ3o^0#CkHLLGB+_YGNf9Zo43$!d1Qjm#(z6ssR!(O zeqZw8U->*;MmGJR%tI%Q->SahH(0J#I{)tBEEB;XzkhlEKS$L{x82{gyG`X}=QN2c zqJqUH1x2?HGJ7d(&5~1ZbWm6%x$uBNgF(Xr28IR$gN_pn1~M!S`@e5!VrejFV$PVe z6OxZKISezbztyNt=GSU!SZlz`&X!?t!@5%TR>XnJ4mbaFy>Rn-FT8a9Rm0kf3o|rp zl5gsK_}cwK<(c5YMF-+viWv%iT`)~PvwLZav&grNwR(zEPv*tW+_Qplx$m|PtE=wo zcx&SVt)@B!>26lsUrpVk5{k4h76Slou|$Rd literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/aa94b8c126db37057eba60ebf9ee8424c4dcd931 b/external/boringssl/fuzz/cert_corpus/aa94b8c126db37057eba60ebf9ee8424c4dcd931 new file mode 100644 index 0000000000000000000000000000000000000000..631376b8904f787aca3347e20f21be6425812c5f GIT binary patch literal 62 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5MuRk}y-o0!L;hMn)zkj)07BHB1IgOsbRlpBnJ8 Saqj;<=iW07ElmS61_J;ucM?ee literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7 b/external/boringssl/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7 new file mode 100644 index 0000000000000000000000000000000000000000..b7a3633177652b78abf217d39587146b9f8e8cf1 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC7?IBVcuY5WngY%-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetH+5eTkuWr^pWxQPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}hFq@H? ziQ(rHgT}@WjEmnI$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9acZc3yv6lb;;ll~PYt9xM zb{f=5TnKGmly%xnaLx;lw8gpgJA|*e|Lcy5DgLwWrnHfy#p>xMBCDoZy~G^OO6ELf4)9yJe#X1RPc8OB010tG>i_@% literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a b/external/boringssl/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a new file mode 100644 index 0000000000000000000000000000000000000000..40a633e6ed5ea18c7456c9e8b70f15b6e6b76436 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krVRZZS4Fo{>m4`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZF1=nXBf{aiZTHiO t@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLIAB9L9+k= literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ad0875493831e5d809ec58af56dc27736d8da4cf b/external/boringssl/fuzz/cert_corpus/ad0875493831e5d809ec58af56dc27736d8da4cf new file mode 100644 index 0000000000000000000000000000000000000000..d90f248971e6765e9c0976bb76404c42978f0370 GIT binary patch literal 61 zcmXqLFlb=Xcx%wa(ooREoUwpeM5MuRk}y-o0!L;hMn)zk4#OAUYM2a~m{ce8KQ-WG RyYhh_-T4IHvu7Ng4gj-kzDxwgqo?Kd#s^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhSIU|?=y-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5?A3TJ!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtB_wZDF|sl+H!<=v0mZqPniv@wZk>@xHu(ERTv;lt zF8aPrj>VJ0?G+QR>{)oj=f?`?ZOkuy71=pDZbj&)S!(WOt>~U>@q%@GR$bweXGap2 zZFt}Cq*H@`p6a!?&7apUn|OT2Nhb+Yk-2MUxJ}aYKlQQQ`JmX;aNU6Sow^NG;cGv= zi_gBq(7RLQhlr@@%>!kjUNme-x|mRgHcwQMZ!R=LB!)(#!u}_o2FiOzoD!k;BP!*!u%@+vLFR~EMhDo z2dZXd^mhJU&6>g^Si7n=b;qeQeg^y?X<j9K4kep0xZBp#b#gyQXtP_ zY+z`hzd(0^cAI8KNlAf~zJ791j$V3dehDa2^^)^*K?244#o)w~oTvxn8Tf(pDzLa4 zxEeUKu>hG22G$0aY#iEbz_iKE#3-fY6ab7Ln1=uW literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b b/external/boringssl/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b new file mode 100644 index 0000000000000000000000000000000000000000..9aff0ede76b3e53acf5aedf5998fc04d126e9f68 GIT binary patch literal 2009 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI2@&27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwgqo?Kd#s^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhQyW?*h&-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9%Q-P8GcCU;FEh~)ny}gVczyFr^GXsk z^Ay4|Q_Bru?&3mr7ch3f?&9IkP0R#_8ra34Ff)iW5N2Zs=GSw!OpNRtUz3;CZx(SGwJGVpiM_nHI%9DYV>U4Nq(c&eDhtT*&`4lrWaH3#1C9@7 zCIcN%gbA_$!?6k7sZ9czc}e*d$d2a*spbcz6ZQs!448?GiYzg}K-7lu4Vc>Gp-HA7 zI}@ruFFAjyzPqQRyAd#4cE_7o>icv4?&r*ztu{cXHOi9#?qPbvIIDUhd@ zuo5Vep(V6|5NdKJzDOn}X99gmR?eLBm^r|2p=TZ_f1+ehLrZMgb3Nhw$-#pyfAWCy jrvmQEg_TZ~3rZ1zRMX6Om-wm0UN=ApUg6keUt$0N5>Rn- literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb b/external/boringssl/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb new file mode 100644 index 0000000000000000000000000000000000000000..fa9b883134436df3e04334cdbd58e7d55ab5e0b8 GIT binary patch literal 70 zcmXqLFlb=1d27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB3!Rs+0Mj8fh5- Ym9ueje4n%PnTD384FeD~m^Q2h0Nb+^*Z=?k literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a b/external/boringssl/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a new file mode 100644 index 0000000000000000000000000000000000000000..92621d97db84002d5dbd455f6a7614e5b8e53bbe GIT binary patch literal 1020 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^$Q&F8BQW^qf=$&%9(qRRd*^AhWCtT(BgyC@-}{!LhU?BfluKq*CF5 zk%62zuc4`-fsuuwg{hgbMHG;0W?*P!W&j3J2ARlKJ%L%p!NcX8nDc8*eodDHE#Z(g$BeX!?rv~q`)Twfj2ukFox{j*}e z1_*rmU_1NjdQHjAmi302r}r#33u#|)Kr8g}#BjUm%`+amTcvitFq+|f_Ta|u<)L!L ze2w~BV&^>b+xKL@B&Bn;e%FYZ-q)--;zv4EM0k%@`JFymW|>STT^170>ytu~Lg@4SqR+^h@+4F;Kp K+#5Iz*qQ)=#tohT literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 b/external/boringssl/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 new file mode 100644 index 0000000000..cfb4fcef4b --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 @@ -0,0 +1 @@ +¿÷œ¹ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b255b3d96ff0a405b5c782cd18fbc50034d09793 b/external/boringssl/fuzz/cert_corpus/b255b3d96ff0a405b5c782cd18fbc50034d09793 new file mode 100644 index 0000000000..62e59a0b4e --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b255b3d96ff0a405b5c782cd18fbc50034d09793 @@ -0,0 +1 @@ +0€0€€1’h A0‚ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63 b/external/boringssl/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63 new file mode 100644 index 0000000000000000000000000000000000000000..0e3021673dc8cf93d3759fde0f6120058bd2849f GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#SIEosmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZF1=nXBf{aiZTHiO t@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLIC;pL2m#6 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 b/external/boringssl/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 new file mode 100644 index 0000000000..456fba1d46 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 @@ -0,0 +1 @@ +¿¹)†ÿ¼; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 b/external/boringssl/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 new file mode 100644 index 0000000000000000000000000000000000000000..a571c87c1ddefa0d2985b5c2a1a19a736995be76 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhSIVqk7!-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$98Ok0C<@tGw3AGupZEEB=|AFK9@xr>ax9<*Jv6lb;;ll~PYt9xM zb{f=5TnKGmly%xnaLx;lw8gpgJA|*e|Lcy5DgLwWrnHfy#p>xMBCDoddc9aigu`>& w?xz#qH=Dhd4a+}uYfo|VgeUdYc1ovh+26)nl+1a|9N@Qb{fu{spIYpN09&j=ZU6uP literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024 b/external/boringssl/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024 new file mode 100644 index 0000000000000000000000000000000000000000..d434d195231b15f6bf73c61a19d9fb9030211feb GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eAQFmf?9F)}jTIwN85_lvl)R9Ic~ zeVZJMCxzQ9CSKXI@P^Ni70%ljU-~Mtb9CH_&`-0}+{;?gJ=fv|>-Ma=!X?j+BrMzT zzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(BetH+5 zeTkuWr^pWxQKOp&+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9cjC>Z zIE&z?G5$Te{{ocF{^X}UJKeX$Qj%f&R42=c+&idwSm(R~GyIx1GKf&_R zFDtWPVaqFVYTCDLSBUI2dM&}M5yVpXbhUBqLyO()W-Uo`Dqo2ie2G7x{h~1Y$xkL` zMh3>kjUNme-x|mRgHcwQMZ!R=LB!)(#!u}_o2FiOzoD!k;BP!*!u%@+vLFR~EMhDo z2dZXd^mhJU&6>g^Si7n=b;qeQeg^y?X<j9K4kep0xZBp#b#gyQXtP_ zY+z`hzd(0^cAI8KNlAf~zJ791j$V3dehDa2^^)^*K?244#o)w~oTvxn8Tf(pDzLa4 zxEeUKu>hG22G$0aY#iEbz_iKE#3-fyYhh_-T4IHvu7Ng4gj-kzDxwgqo?Kd#s^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhQyVPI}z-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9c?N+9G+!n@Zb(bpj8i-mFL?)4-p-3u8 zn@Htyp%zGu7W_{xSm!dy<}%^pK#9(1vzi&F-D=b*K+Y!;1qNj@9=qFUwJWz+>EhX{ z260K?ys97^6th)H3yoG=LcYJ=1QSyT+dw81aZO%HK@p$WzrYZYAPvJKe*S`8lAo0b zo`-j%dMgZrxrUtJqDRLMwF}Btd>8qA%chkt*504KbmC*`H*a3S*#5Gs<0m8<-*WZ% z>p!%WSsGcS0D#5HIb}y?mBqqZN9K!4-~uo#Y&8Ue`AQ`+(FTXdYBrXT@u1?70NIMC zh%%ctd7QLTM?2kCv(;pD)Bmf>OA8uE(vYx*7n7Hk0%|UVw1xSe$|#Wq>1pOwr^n^y zk1>H<3K4$AWMOl--p1q^ZAx7#u*mZHZ6J#U7>h^+94cy?AX{?7T8tO-kqbmeC_D^`jvb7ZeOX2aP$~P1_sMMi@2QgOV@b+PAYqN zN7kYEnawfU$L5jVcTXlq2rks3$u$ANGgQL&k;F&Snd=#;DDv#;sP}d!|N6H!Tb4Yq zbEWF1l+*Gy%~&`V_X_S9Zc0qKL$!*u`}68ce^OWWeqy9#WG9)Xp?)^^&Ad=q@j4Ne?kn*2p2=W9c0OMZ%`G}PA0M6M}2y2Dl1uq&m0W9tXmPPVsDPwW|Y{e=eLSU8# zOfL75M`Wm_A(i`!cR6X{h@%2o=rxGP(%^WbGbOO;^N|kWKP<}cnCzO5{g9_LJ%Sh zh1EP=D9+s-?5sh}a|UHYtoA&ngtx5IM7z{Zx`=UE-Hfwz{sa<)0IRGNym2SYZg@!% z<^$omO7YdH={Hf%e6b%$hy9zyKCig5(@|l*_szt>y67iUQ(cDZI;!Ool!sr-sXDQ@ zR~uSCnhtQ*+*tV5McIIU=3wp)*W=G`F4aU(-ln5#yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9*ghtK*zQ}aWL zN{dSrJoA$E45bYuLAEjr3&F+RbMliCa}=B%4VoC0kiEgk%D~*j$j<;2=VB6IlsLn9 zE4j(w?-y}psj#}}`!+ciPYSnJOuVvZ;SHZ3E1b76zw}jP=jgZ|SorSR!$W7~%oyV=cJlIB#t5;OP` ze?a?1VKyT(6T{CZ291p$7#F`akOu~%tTKy)fmnlx$Fq!|+Lty>z3zTPSwX5p2gU}&_I8I?gH&L&5V+g0xNy}lolhUpij7U!21 zC8rhxSq1sUnI-u}mB@(#n6{Z48yU(T3g!8EiwU(Eux)DOIRAm;`0>KJw0DQzUa^+{ z|KY<4ziZAG8+ICmF1k?LERl8EOmNN%kF>?P^*e;Gxc}>piYflH?xwVnq{Zs#CL*h* zS-oB?Bf{aiZTHiO@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPFEKC0XxX N;-?lw_OoXe0szB-P%8ic literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b5f5a28954d2634baf685a1790ce013ca0f0f951 b/external/boringssl/fuzz/cert_corpus/b5f5a28954d2634baf685a1790ce013ca0f0f951 new file mode 100644 index 0000000000000000000000000000000000000000..72f9c5924d26f21167e30156c6f354ebbf727242 GIT binary patch literal 72 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz Z0M)Z`a_s*;XXi5wElnE+AOH%j1powJ6|n#S literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 b/external/boringssl/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 new file mode 100644 index 0000000000..c7d4fda706 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 @@ -0,0 +1 @@ +0}‚00 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b63a8d0e7c1848019b4e4e8e19d14adec00b7c19 b/external/boringssl/fuzz/cert_corpus/b63a8d0e7c1848019b4e4e8e19d14adec00b7c19 new file mode 100644 index 0000000000000000000000000000000000000000..540bf684dbcba2fef25f021a74a1bd27042a90e3 GIT binary patch literal 1023 zcmXqLFlb=Xcx%vPpw3)t(8Tm?0W%XL6BD!0?q>$PY@Awc9&O)w85vnw84UakxeYkk zm_u3En3+O@4FwGNKpZY%cGtqv%(TP`LtO)HkO;T13RFZPI5oMnC{@8ZwWuUBEi*Z> zBvrw&v?L?HD6^!}Ku(<3z{tSV$k4#V00^SQc?~TLEZ|%NC%ApWAp67&L?HI@x~Jxc z6qOd2D0t>2>lsQLNP@(fg@xea?m78Mi8%_+js{JPO32<|WMyD(V&rE4igPhFF)}jT zIwO&6@b`=WfFZ?UnDMQK2^ey!llh+l?c&(~ea_BjZCV^!4VIdFSu48dTD)N0 zo>f=4|SorSR!$W7~%oyV=cJlIB#t z5;OP`e?a?1VfK@sOw5c7jEfsT7&N{$kOxMCtTKy)fmnlx$Fq!|+Lty>z3zTPSwX?o#qDtgs2FxwYjr$G$H!_qlJrv6G^A;0oGho})$Z?*D zBLI?I6v4@bpN;ba$MNHZb!qPoy}e>B|Np~>6Mom6EjH{lsFk=7+Po<1w3*6uE$f{|VUN4pr;qctH`{~5@&1SDqKjWQ2BIBnPdjN3?Xc_J%A`v>H%~RA_wz(LGjd3Y= zxLp>`!MZAyKkH!Fpa?pR2A!VPr=_Rr3(znfXk9u4eg(ijb1QMUB+F!Fi#dmlHPH%? z^IJV9@!8K3pWQD$GbrBhT*ZsRBc^k1o6E%7l(Sf-Jebt*{-pA{Vn7i{YPfWwB(l?9&|Nr`B49>r>OMKimJAbEfQVb2yMq3-yN>9Z1v)$;KfTI4s9Km zl*ngWtPu{E5S4iF^bQwkRr5<}qfsgHdKN4i{U@noTZ78FYqc3UrXB zqhTyh5n^hj9`wN>ObXc);oFCgL>6ISxYrzRr%Q=)t)YiNY#`aP=>9klH=k|qK-N~o z@nQlsR1s=K7@r0yMUjNa1D5_w;W#xH3eZ{lG6zImyv5}z8>iKlm9io0wTA3WgHB_1 zxI!l5!O3PT%h+5_I&=kRc9!*;6GlA4 z#ThAw1r={^(BBm7UsP@1=0Cn*`<{EA>#IgdHzr-^tbMS(zNN8sQcRkB!|ui@Yc)A1 ze}6OUD@DU>b?&`YYR}TyyZ^X5zw{iorb+%-{zBUKN2YA8a-67dZp~Mn`R4tJ>ysCr zzIwJc)_&6HZ$Dr4QS6!gpH6g~o2SpaF*j$mx+gaw{hwn0sdu(z#A5p!h>ZHM$R54s z+c?1oUDGFWQc>I|V}`xEAmf+6((_~)?emgVKTOyuKdieGLynqB*>CJhop4QmP?Wx+ zXno~vMJ_y?e?)cDUV6QoAaM-eT5}(2I-l}ts^8MBI=8psqTy14a$rts<9nOhLr6HX zw9&F=)!(}W3x`H6|9Cm`#mUn~kOoNLofiO!{`iVR!14jaEG~p`y+)=24O*Ytr>aZo z1J&$69f#pue1-5;phW?v))}Zovk4(<1)~oL%+t$)@;GIH$&e+a5IPu)hm3ys30$G( zzv&#OMQfhETafiQ#^}#(+-%%2XMryhN#buJ+S0X*K&>Qco%9C3qIueyYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fiZU=aG4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X9EpbB8Z<1owsnj+6)Y+z`hzd(0^cAI8KNlAf~ zzJ791j$V3dehDb%^^)^*K?244#o!c{oTvxn8Tf%*pupm8;A-H^#sXwA7+4!vvTB|Np~>6Mom6EjH{l zsFk=7+Po<1w3*(dtJ*6$F$;{LBYDyI0)x|`BQk`@iCr<;hZnr8KSv5W|Z z=eFHXC%$hsdkqXQ*|7XmxAqh#Pk2&aZKrhFmi=wKMai7U%mIE2*UxyD_^HKS2mo)N BQ78Za literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac b/external/boringssl/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac new file mode 100644 index 0000000000000000000000000000000000000000..d01d05e83f2b74f27be3e667a37f3681f43dd411 GIT binary patch literal 1106 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?l=Ho&do;Nfyk%*jm4FUreIG!!!s z0a?Y)!|R)0npcvTnWqqznOY8a7Z0+#Bn-qrigS7R6PYt}^wRU|fiBid&d)W7G!SNE z2YU0IEfXUf2bjUk$j-?@p`GxWo{G8Xbzxt?(IfLv5 zA2o-mpTF%~G~42FLsItZmg@6w7I7K1De1q7y}Y+NV{sE>wm}nPx`8avYFSklkb^n2 z*%(<_*_nY>L0L=&Iv{C57GTgd@#iLjT?YzJkn5TRGV_x1D}e5Wi5PH$RP(d2Ff*|? z7-YbVVPs^9F^DqIhVc!U+T=4zN(!v>^$W5yk@V}kdpf!s=_MDHASq^qD^AYIOwB7P zHbmBupIlr3@dF==7>meZvu9nCa~Sos;{&7pt}hTw4_JNGfCuC%VMfOPEKCLr2J#@D zG7B)!8$`VBvWZFW`IfP@>}%t;-APirq8jxL6hR6USfmUjfI7K=A;H3Ut&)kA(SU=E zExnNkmQ^ObtQ zuIKk9AO4lk(`97S56V1r()g|F8-9c3YNhk<9?mim4D$Pz_y2QLt#sS{O}pDvPIgX{ zxFRZ8Y*Jv*V9>y%@z$V;rNN+yIb#8{h)9FsBw?nE1&+Wx!^l*0`yjKI!qzOgMkbDc zjBhne22F|%3X3Ec9=Ks$DSIp8z-5PHm3rb;IYevKHWFN+{C4Sj@%@ E03C-|O#lD@ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 b/external/boringssl/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 new file mode 100644 index 0000000000000000000000000000000000000000..2b91c143902559b860b20ef059d831b46ccd4a3c GIT binary patch literal 1002 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?l=Ho&do;Nfyk%*jm4FUreIG!!!s z0a?Y)!|R)0npcvTnWqqznOY8a7Y~GkzM7waYG=Nd#B z2(z&Ry?M@-iII&1%wT3@XLe#>k-W2|Nj%-(%pm&5OS#i^epjRXLiq}Q&g zCB=rwI`Wf?3m|^rV-aH!Ic)Z z#8YMg26}^t*IhO-={?^vww8Tu+_pPOYFAXFzJVf0fdY$^fdo(|7ceAP7_U__u`(KP zu(72#@&HqzfdNQ~Jd37*x`FBfpj?m^9uRG_f=oG%;r^U=|T+Fq|aJl(E1Om}eN7if$id_EOlICD+Kr z5s>k%hRL8w(LrI6s3pcO#!m3NxUp1($02)K3Ja=J+W=--< moey8TU#JKkTy!A*rI?{0EF(T$Fik$QdufZa$hVEPddvXhPa^LC literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/b88401cca46b7cc9cf588dbec641411101bbce68 b/external/boringssl/fuzz/cert_corpus/b88401cca46b7cc9cf588dbec641411101bbce68 new file mode 100644 index 0000000000000000000000000000000000000000..2347c46f952aa6b7c4ab15b1a4966cd1fc11a1d6 GIT binary patch literal 2056 zcmZ{ldstI-7{||T7hy2R)?^YgMHEEXdj_n5msFCe!9)p7FcH>)P38`4BS8YUX_T22 z_MlX#6ErO!^YWyIU|^R=QByK7wTq7>gegK^P|L92nS#(|f9yHG_q@OJet+-zzMlgw z@+`QB&)g(|6NE6gftusHpeY@E_(R5(%_zI$gX7*j3}({aFoaL0QhX_qnnFuK!Y#a{ zUOJY|No15}i-8V-U@k~XpX7pOMmf`BXRH>+uAEw6H?mffy-2B3!-!!%bPNq@Ev=2w zL}}B|QUkPF1D;36S;I8mx^P1C3P=H1)$Mgvwn`m4aF_9Tv(QgO4Vw)%bTFOIC-tE-AnU#s>~myJ?g zd*R!|#l{*Jo(nEK2Le&)zz~WPEDY!4Jf46=r5;@oFrK?Dp-}5w|5WE1YO-Xpg#-0^ zbJ=2wA_;*5jD3&6acUuqO@r{h01#zCM!P*PPNmArH4S)xN;h+=P915m+6N@#{mBNi ziLuyi^uQgg!It;%5WbY0l6|3RfBhXZ9vPl7Ctd%YTauH!vlT>~EGdpZpa{Sqh+73y zsOt{dtRMOEfchTe{+Dh$57cE1Ka}QF!ALGaNeu^ow9^ZjFkmkDIykaxswAm&4eJJ>z4 z|4jeW0P|ym5Aishbm2J0Xish0qTjw?apKseX1ogQ6;h9Lky7tEn#F48p&<`Hlq2P<&AtHoe zdVYZ^JF}3EK%PSpZ|Ueq5oHQvD6lfhc*bfsWt$9{cIGiDI81;VV$?K5b70^wp#^RK z5~dBV_mBvvo{x@UpR*R&>nGJYx=&`|@Af%7nA12Kl; zUIgcd3n%>z@Yk(j!Ncd3reB@*4Li&$ zT(eQz!8^F5G=FRRmy18x)8)9lI#j$VjIyKY?1$UTFtt(D!CJrQ%hF`=f|daS&mDK-4-<_(jp#=Lm);;EI2 z{Nwueme%4A6v7XUxycd3EU&VL2bHU1?v!g2C-rO<(5{=6%jcZr` zxs&&zNK*1q3G?aklX^6neURV*iCE$BN1&La2I3jchd3@Fh>8LlRPG3Ocv;vZh8e5~ z+6-&wUMh!e6$;o?HjjA>nTTd)&~tm0ln!85-$zS;abJ=|sq@|G5YMO3Z44$rY#$>D zTpqza--aN$Y}vBG1+0vXEwCCGo65@Mu{M*PwH6ID3i3PYbYd@E^0VllmHU+ef1gu$ zx?6bkXntw-_0Kz7CImg`?mnhJ8?W6{3nl)|sVl3OoX|+BI%Z_oEM4)bv_;puCT*cj zaVMZu6uM}XMG{p1;jOrzMT};D%=o;V1aI)n??djP+50#5fDk6%|M+}>TA|&!AzJp) z`ZHH+o|Fk^9;j<8?^>z38aR(VexcrGc>D5-;>n{naNu53;)?48*|h;^EIt%*@eC2fJ7=IX~AR(mLHEluL-{>BE;KVHh6uJgMZw zXv6phOl|TRB_#z``uYXgnMnHe-8~)Mjr5X>N{|#Y!WAdyWTxho6dNMz$WJaVfcSxr zMT|w{u-UV&$vKRA+VO$We%BWWrU$IPYQO_>l`tdYe-H4dNwG|g;Xx1d()cNqW`-RFg!Gntq#J?0X6#Tki zntW#W(iUge!qUvN#0o=QVB7(1<`!0giYNr9CYKhaDmbSWm1L%6CMTApA~GB(w;322 zm>L-xn1J#ZD7RS{SirdkPN@EZW-KmYUiZ}ekfPG!5>VFGGn6)v1lh_gECd&K&&f|p z%u#T5G!Xf=u~tuU>dCy=nR`|+F8AHmVRhAg9dE5moF%uIP$|#!|2)3B;lMD)TGBKz dDuDu^L)_DV8(IJ{vNA9m004EaSsnlY literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399 b/external/boringssl/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399 new file mode 100644 index 0000000000000000000000000000000000000000..89f479aa15a8a7823f42499e721a3f06ea0aadbd GIT binary patch literal 745 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O&e2?c8#|hO)MY@xIsXpLV#NKEno(+u0dE#j6lP(_p=1@MV^c{ z;AP{~YV&CO&dbQi&B|clX~=EB$;KSY!Y0fV8f++RAPC}c33IvU=cnhSDtP848>$*8 zg9Mp{W#ED(sYQ7uC8ep33K{uDnI)A9?nVZ3;=G2Yh6Y9!h8Ct~#uiaPu9<Xj4ta3oLii3yCIWZ?QEx#x)Gtp4YKm=%&COZ$WZ+>ZBNn&Q6LRe;MIow@5$nKIb z5Cgl5hd(zlGe<8S>|(v-{9J=b17S9Hpf}IiGBL7ofEmn;?95IKERuJ&G>NDCn;B?C z|9B~Py3X%vlwT-c!OwX;`x&ZLj>?*E@KJM^`uW?=MYAm)HzZ}hZm9-_WGyfxpDh5! z3lkHw(C%l*fyfFBL_gF(6fod}1R}d@VQFSsVuhiufi_5lTUZ4uq7a;#Tw0W>;G9}i zl9`s7oLG{o;8r7kAIePfE;DaCS6kVpKx*1|us2a}y&!g8?HKQxhX2!>uzC27kYZ qD@%pdMc=o{+3}=sd&R^ndlugCIsax6mrHfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue z8+_CprhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&v%XSwIfv z&}L&~Wo2h(gtM3obb!*bf-JzGYeIKjlR#!(Qho)pd$~cX`B_+)nb;c)GGN9qGP1-N zL>Xwq_y$aE@);#11y=g{1=*QM`t{vC9o-G}l8Z`^6f?pVC+B3Q=9Ls1BJ0RcE-nE3 zL6(n2j78+I*|V<6IgEPR@qy8P*B1z;2dutozyorXFeBrC7A6A*19=cnnFSc=4I*B5 z*~Fyxe9PEc_O)@_?j)&QQH}ZriXa6FEK&v%K%HE`FkxZ5R>{Q5Xu!e7mfpw%Ooavp zASLoFng;3ystc4CD8ikH#Xm+s|Ky-0SLP;0Mut?gbMqGZEssp_+4yhgEA@a~&+kh< z-2Z*fPJ_0;@_D+9Z2Cc&hfW&5Rei&6uw1Ql{@ue_CW1kJ|MLESj;fVz+qAn)YjjXpB)Raw4eLtTTM-8?JKX%!^}@~Tz3|fYR}E_`F3ixZ zNxrG`;cNE`m1lwn7afRyDP}16b-^_G%ND&?8}pT}1>d>$*?kzkwX0+YTAdG?>?wC?&hQN%ZYk6XZ`>eQ#13xwX! apY9{vI8*YwbRCaIoKl{k{2l}P=VAaIhe<5} literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e b/external/boringssl/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e new file mode 100644 index 0000000000000000000000000000000000000000..f4e18e0836fe140a73723150db143a1b32db465a GIT binary patch literal 71 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBiZy Y0M)Z`a(th&^O=U0rVRrS07cdU0O*bs^8f$< literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068 b/external/boringssl/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068 new file mode 100644 index 0000000000000000000000000000000000000000..f0bbba61e9f9d79d486db737931779e75268f854 GIT binary patch literal 896 zcmZXTUr1A77{<@{oo{DzZklY&KRGwEY0cW+GjWYT$hugDnGy?}h3Qy3hi&H!Jyv4G z@esR+u9B`2Sr&BBO+f{-KL*i71a=YHO%V|pm0d+z7iHg3r&8zYd(Zbi=Y5{v%K;Ts zyyF{aLLy8~|B$Z)z zH~=-}R=$~sK!^`D2b)4sS_Xj+1VMkIAg)icZJK1Vm=E-dKsB=+$Rue{hLWJ61URW( zr-$evO^qBf7>q0(wRXa=OTR87l(x2(NFFQwNEc?BUeZJB*0n97)Gwd)B?@7<;xrop zXDJ~pHmV>LzK0MwPN6pzYQR~SpeUKWet#w@Zs^nga9e9Q;EN3?8_k=5jFkdfSH@Ce zTv7)4&2l+5m|0C$LL9{YG&p~8EQNfHyKRBd#eioRJ>ddYU-aqgw+_t h#6vR^*E()?pKQPLC;z3PbL!K(%J;ur(r(20{{krd^)Ubd literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92 b/external/boringssl/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92 new file mode 100644 index 0000000000000000000000000000000000000000..8a708456227054b410deb86b9d235fd2dfbff369 GIT binary patch literal 1110 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhVDRT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{(pLP%EeaBw*%=47Vj7v*Ip8j2Z+ zfUIKY7AE3LE4J8c3z|P{~&rQtC(MtzAST8w0*C5hB zn2jCi%X79&jO-j>1~Vf&vl9c0h zRAh-Uh%(TI@eP>TH@6-if{|7 zKt&XSQ6{0g&K2Bq@{>smR>5Gu%+J+9W;yQy<%%4~k6<*9~~zsoPK$zV_2Q Io9s&r0Q%=HYXATM literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/bd32136e6ec853a56e70060a2c308187b8fccf65 b/external/boringssl/fuzz/cert_corpus/bd32136e6ec853a56e70060a2c308187b8fccf65 new file mode 100644 index 0000000000000000000000000000000000000000..3383d6e72bd7426a261e9f0c415e563d8b324398 GIT binary patch literal 1188 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhV1NP|%>kpn*x_tw9q@gFzE>#sX#$ zk%st5!b}+p9Dz20tTKH1t%eC`wd!R4r$FmC_J5zV^I4k~hY173z>?IWywnl}$I_CF z{G!Z~N`(hT26E!OhNgxFMizz^re?+#Q9!PlfwiHLnE@C?8DwI0CkGFgb7Ib~wEUvH zOm#ys0}+rr*?D+<^Gowe5;OA@!ZK6K;hy3__LPKy7}!%h{JDvlIeO_}@9HJz=Nd#B z2(z&R!|0qX6C)c3n8D1*&g{g%B6(*^lX$wnu|f2YmvX1;{H{j%h4K~roY%9Tp<3mr ztoa5XHHWF6zwKN!+v0IUQugbX>ho_FaT&EK>A#7+ytg`IaT8;7+G1_nSoY8Sxg2xAZbAsV7ND-xDFWLwZMRV28mN&_&GcdX`zRh1dXJ-vCx~zc4d4f_0%l`ks1d^GS zSYfDZpbavDTUZ5X1V}_7I5oMnC{@8ZwWuUBEi*Z>1ePQgAtebzlq3<50Z9_6h*$?j zxq*>^sga?92`G+1QEp*i0p}Vx!My@bnb64P66SSJ%?~LmEiM72O+7#y22&TjwCGG@V?}D-Vb1F^648Fu4(0);v z{p2STGb01z;>HgKjc*O)L5WbA1(;77L_D5l{M5d*Y3gC#V%)bIj#C$Ab wEFuT0W@Pks{$9yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fiZU=aG4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zN?@X3M^4<#jg1Ut4~6plyv2mt4A?d`a-9Fbar}5;UD~@tZ?9O(|Nrpegx@u1iw!#s zY9%g&HZRILZ6-M9g-6=r-1;5DSKR+~N5vHXS$9*~NYY~UbQ6(P)2v=EmJ#9b+_wAa u#P`i+uVusXPu<#6oIK%4eYKs^X9y15{EnGk2UE-$}dm#Wd*g*aO literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def b/external/boringssl/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def new file mode 100644 index 0000000000000000000000000000000000000000..583b122948440da89ed7329913fc1db11f6f06f3 GIT binary patch literal 976 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OkCWC z0tS3+%)%xtTbV8%To0nT3Vm;_f;5Nr^cM&W;96j7rE}VPs`sZerwT z0E%;IGBq(WGTb^Nk!SY7men;eTLh1)A8UfHwohR=@`&fAz@`YN(>bli&2 zPqWnA%UaPr*Wv~1_N=luHs>0WPdKaI4iJ^C=$PW=w)0+p}7FQRYn7IFBsP@?l)9vP{ zrJT8cu3571l;5)}SF2Y_o(;Ws;?1Qvi{Pg*{ynf(PbOwY2FAsW9}F7b8ps1fQdXHo!a%G+#N%1UPwh*a zre1fyp{yX_Z#-kd{3`~sAO(CZVk{yDs%B*LcK%+?n!+PkyQ(&I$Eh=Z2K*ptVMfOP zEUX61Knj#hLS^|u0xZC^#b#gy;>)ub8yFhsFVJ0}{jp6mqokz3N?$*@C`T_nHNOND zv3kk*xgddJ{bF$XNlw%Q@(lbI7%(w37#M)eP&mTkZs2O*%*Fy_GZ<;djm1V#7{@T8Rsx&5N>5n+eW&;gPmDw|mglC)So-9%*7v`eoS%ZPAzZrlBI;`?T^*Ro;x%o!=nr*7>jPM+|jzFKuM dzgAPj+P4OFN~dkv-^N#z%z4br8{oHaJpkfyTXO&a literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf b/external/boringssl/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf new file mode 100644 index 0000000000000000000000000000000000000000..f57628660551564f8bfcaaa418affc95a98fb80d GIT binary patch literal 12 RcmXqLFlb<6dacL+qyZMu1EBx_ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/be96bcebf50e143552339a23071c9994bb7b5548 b/external/boringssl/fuzz/cert_corpus/be96bcebf50e143552339a23071c9994bb7b5548 new file mode 100644 index 0000000000000000000000000000000000000000..415c590339910e60a893325238fb64450b741184 GIT binary patch literal 1106 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG?l=+Tm7l@NhXN=47Vj7v*Ip8j2Z+ zfUIKY;q}e`zN;iLGfyEbGqoJee)?g7!gFzE> z#sX#$kp{y_!b}+p9D#uV3WWf$r}UEZa}6R5gxT1EA#u)@iII&1%wT3@XLe#>k-W2| zNj%-(*dY4HOS#i^epjRXLiq}Q&gE__g@u`ky}=*@Y)rXwqtTbS1lg}tADd4cu*DuJzbUysHYtt80~j`fna*T>Z=AkASVkmGX7^_ zGJwTR6H?sdBF7DbfjmgLG7B(P8$`VBvWZFW;V?w@BCi_fw~Vc2UmLgWPLkRc)u?Zv z2-2azB4r=}w2KQEuq=$%Dw$Xr4LI1?(i?ezF>YW0QXBHU9rLLdh% zgD^KSGBTuEoSV1MZ+T>b&&Gc{U#SP|dVXK>;a~YYT}C$jpv*%jjo+%i;Wt>WRyzOg z;VcuuAisZk|3637O1ItLw7X5^Wal)AE24tMCIv;e4>EfxY|WBubWm6%x$wXZ>q^;M z5eF_i-2Bt^!r1G*@Y3~H4Qned%z#9tmS#=zO`Q*4yI-h06Fj)+K>SNFL&2{Lrpae^ zFKuxa`L?lEPjTwWyx5t0RxmF2-PU1s)qNdrtxKFGx0p~V&-DL1zPjP_SlNyQ+e8yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9+&(#wePRY85c_!DQ}aWLN{dSrJoA$E z45bYuLE_AELU3{SocyH390g}bgC<5LWN$FCGB7tW@-qO%x$ZYHG78)}Bav+I_lvl) zR9Ic~eVZJMCxzQ9CSKXI@P^Ni70%n3U-~Mtb9CH_&`-0}+{;?gJ=fv|>-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetH+5eTkuWr^pWxQPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)CWDFGeE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}hF#E|* zCT2zk#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9KJw0DQzUa^+{|KY<4ziZAG z8+IDhN?ZtSUX*p(OmNN%kF>?P^*e;Gxc}>piYflH?xwVnq{Zs#CL*h*S-oB?Bf{ai xZTHiO@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLIA(+LP-Ds literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28 b/external/boringssl/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28 new file mode 100644 index 0000000000000000000000000000000000000000..905033306bca030a2023cf16060a1a326dc809d8 GIT binary patch literal 1280 zcmb`HUr19?9LIO=J-eH8bIQgvOP!giEwoG*SQU}DDXa=bMEh+@ArIvpL0P5 znQ8tC3YN-hctIS`sfWj_- zk}Lp|t`j6FdC=ubM#RF-_gucNPM_NuOi4w>?fK$hR1C$X5x($6%#{d^B-c+@hHcpT z)U$MDDvF$rGyOw7Z!#6(zB>zGq<$?3{lW}rppMQOFzJVEJ@$^X?R>lz{N%Jq^WC_Wo~B6M;J10!^^-3+UKH`JW-b z{_X!Dr%dJ`&yBW%Ja2b11S%*;~=%S z*C5hBn2jCi&2zR)jB*@6#z|XdMs{W=1{TRXTbjhv{f!Nxf4r1CUFUZ-$}g0!;OD%a z{S4JAM`g`7_^3Hd{rqj`qS+RY8)B&Bn;e%FfIPXE7P*fTRUkfI-)U?z$#{%)F%h3S{?kgH-dgurM>RHyC8V zjA3MCi7|*$(1!61nA+qsN=gc>^z{p}Gm-S`yL&pi8|ft%l^7rtGr|=o=VYell@uEy z>&QBa0|THETX_~u19bz{16^n)@Foiu){`i9?NxmxM`yN9z(1cUtk<^BI0RV&?gf79+Zm6M&* zB(8`G7Mm0l-9E_drLZ+iuF*kZk>tVy1`P%c3m6z03=BF>Fc`?NH0=Mrp^2rzpouwS z&Q3@+(&RAAu>Mw~I+d4Y zp;?oBQ|H6i?iVW01P?Ac5dTulQ1I)5Y4VxfOIw^pzHO}4Q=ED-FLvgh6^zS$w{=)u zbzjF@>k?3nxZ~h*)fJvOysZTQ( x2)&;_-AA}_rsQ|&Iv$NUr946TJuAOhJ>p3<+iI#)knYC))zm#Ip-B5;F#u&`MT!6b literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea b/external/boringssl/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea new file mode 100644 index 0000000000..cdce1db360 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea @@ -0,0 +1 @@ +¿óµ90† \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6 b/external/boringssl/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6 new file mode 100644 index 0000000000000000000000000000000000000000..473c58d51d0e36c44165fb022328d99950baef03 GIT binary patch literal 1102 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf?MoV;X1RRd*^AhWOxRM0c8B(*3nwM41l!qCFh%-A9d$Tc%CG%_;)gD8VctX6UGa5*RDWTxd8<-JTa6f+P3 zT6KY)hu1g1^v}k`%shp#%+zwYyLe#k@&vj|!axk{E*}2e#LOJMbg+x{lJj#7A`OJu z*n!?WXUoLM#sOw9GqN)~F|bJ9+0rDQ?r&@m{o|$F={mowQGTI(1wZHY>}RM}IVx+u z!AH$u>gR7e7tOYK+>n(0x~2O3n?+nkZA$uYVlVHl&RE>Um~GI+m~J2ov|3h`1>|53 zZ8k<$R(58fRZtd_feuJokOdfYP3W#`63EO;%CA6nFE>avKMM;p6MKU}2Fw^nMwS=@ z^(X^vn1BIOn|ww|Nr9EVenEC7k^%beo{sKDddWp4aK%~%jBv%tIhm<>CB=rwI`Wf? z3m~50V-aH!Ic)Z#8YMghI)gD z*IhO-={?^vww8Tu+_pPOYFAXFzJVf0fdY$^fdo(|7ceMT7_U__u`(KPu(72#@&J>e zfdNQ~Jd37*x@S^G(bd3z$Vj8Vn~1Gi5Ar1g2P^T8V&+Z#7K7B&<4_ z|EU2#n}O;A~97F==1gCK3CPqevREu--7WyrZOz_$GZ|5uZfL*Je-zjU*3O>&r!9~ZTC0rZc{ngIZfh>4 z!EG;vgIk%4vgG!EZ*)-5l3aM;hIOUvt%w7c9d7>Vdg12vUU=#HtA@1|7iMVIB;VBe z@U{De$}_=(iw?wFy%aMP{JLP8d}jC37H5%f8*B9xr=HAW0r_WjhjV6Fq0AriNC5N#BJ$`%iOPcm10v;+wz6 zEkM)2j$u-D>eI{xLht8K_YrQKDfwNxjz=R-DNj&-&&n@Wk9bnewwme`q`Pq&AcegF O*0AS54*RdB?oj{)@>R6} literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c3c6d8be363e9b8535dc6586a6b01122efefdea9 b/external/boringssl/fuzz/cert_corpus/c3c6d8be363e9b8535dc6586a6b01122efefdea9 new file mode 100644 index 0000000000000000000000000000000000000000..f2332b4973afb3e855567ae1c3c6f8d063b03704 GIT binary patch literal 823 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5G~pk}!~c&7g^C-vVYPMkXeX?ENf(e32)k4S3l& zwc0$|zVk9Nao2S6JxeP6Jxr8EYLZ!sw^N+aA>nJva+%>1FeFxm<)74 z(t<3&;B11qcryP}V2p6={|*Xlkkgw4GV_x1E08_I4bsNX!otkN-e8acGmnvxCB`7i zKpVz4U}}@kC@Cqh($_D@&P39$@9yd7Zlsr7RDz_K5w18nCo?s#q}UKyM}Bf~0mL(W zEMhDohs~aKP0nG|(~b{}_Pf47Fg;-PRRbQ7tArUD|FbX|Fc`>#c*-om7- zz(9+`2&77$MbkjtK$U^TV1e=iMYv^IHyDx@K--U}Q+OI5%&h-}1-=pN;=^ VzETg^_58l%!@u%*x{Pf4K>$-&-U|Q# literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b b/external/boringssl/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b new file mode 100644 index 0000000000000000000000000000000000000000..a4c5ee24aeb29a80a5d4b554a9903a4024197296 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zB!S|r%)&x&ard13q{JKrXGeo3MkQo#FtRc*H!<=vGBj}+FsU~>b^Nk! zSY7men;eTLh1)A8UfHwohR=@`&fAz@`YN(>bli&2PqWnA%UaPr*Wv~1_N=luHs>0WP zdKaI4iJ^C=$PW=w)0+p}7FQRYn7IFBsP@?l)9vP{rJT8cu3571l;5)}SF2Y_o(;Ws z;?1Qvi{Pg*{yn}D-Vb1Gkn8GMO9p#7pS`^irx zW=00a#f={f8s8eo1A|dknMJ}ttU<)%S;kN8OPi)%cfX;mAmDF2W5WC^2C^Upd@N!t zA_uBwWb}6aUd@`qBUrntHg(6TGkymAAZcMn#{Vp=2FySToIYgvK>{qmM8#%c1yUf- zVr*b&pua$Ofp(i_MoCG5mA-y*QI1}EYJLeQQuUJab3p>d`o-YHlbomr8wHdH&YUDWof#dk`!n(9~hu&VXmjD0Z!wJ7@&K4VX z8q`W$2yI@Jb=pjD&I^yU#kuu6gs-^&>yC;k{ggsTtEOFgy;w$s!*kp2 vrxV{do4u9|%RhB%PjT{uC-v2KN~dkv-^N>%%z4Zl;J0x7jCYBjTI_`YVh}-= literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 b/external/boringssl/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 new file mode 100644 index 0000000000000000000000000000000000000000..620119d8d6fd299196642a00eefb039b29e8875a GIT binary patch literal 976 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(pFrjI4eP2E2yc2Apinp)72|OkCWC z0tS3+%)%xtT|jfS4MfC3 z4MA3L3G=$A=7$uO7MCb^<|XSHN*hRm#F>SK;NtE%`ALa63eJuOO^ix#zwk0LGO{u- zH!<=v0L8g9nVJ|G8E&1CNH+NUMO;}btS8RpDzty^GJj#L&A_CFRfi>r%HOx%AmRQv3O z>2`C}QqJ5z*DP6h%J12gtJNzd&xYPR@#a#TMex%Y{~q0c0m^27(w?2}TVg56uzf0% z(8XO~^CBiEl``RJEfu(0KoI5q9twkt&T8oica)(B!Le7f4$ z_MydYc5Abiq&bzZ!~zVy#2?UpQJDSYClfOx1LNYx4+f2I4dj6#DXYvPVIbBZ;_)ow zr}m{yQ?I+nRWmYrJAbccP2mx&T~(X9R1HT0ZObiVM1|TC8jjc&2G$0aY#iEb zjI6BeOpIc>ATx`BhL)F?qZ(S2TAW{6l$@$xlv<;djm1V#7{@T8Rsx&5N>5n+eW&;gPmD zw|mglC)So-9%*7v`eoS%ZPAzZrlBI;`?T^*Ro;x%o!=nr*7>j lPM+|jzFKuMzgAPj+P4OFN~dkv-^N#z%z4br8{oHaJpdKFS~vgz literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3 b/external/boringssl/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3 new file mode 100644 index 0000000000000000000000000000000000000000..fac8866af9376a38c3424df256b3c84064729930 GIT binary patch literal 1853 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}-84NrPxeYkkm_u3E z446WL4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{(p!bnze@NhXN=47Vj7v*Ip8j2Z+ zfUIKY;q}cg%_~XF%u@)*{_k9%Oe(7>I%0#lxSQn3)B z&Bn;e%FYb53d&+K&;dycvH*jw3Eg!~0-1S9`4!0SS@OZM*Ce~AebJo`lXaLK|Ey^V4ydMc->_a zliu?!V{6&h#%;Tkq;^F$>KiD66ezGr8At$iasfkvh4ES?6Dy+u2OC@ZLLOi$G%x@u zk!R5~P&ZIrpu9j4?nE5^$w5l4tc=_Y%uS4p45=39<}LJF9+}{?@!!r@>H)i+-6^n)@Foiu){`i9$JxmxM`yN9z(1cUtk<^BI0RV&?gf79+Zm6M&* zB(8`G7Mm0l-9E_drLZ+iuF*kZk>tVyH>@jVZ$%uq>~Ql>*9$kV_rgopUp1_)xG+Pr zCi$k$hp*i)RGtYQTy!A*rI?}M*9Ft$GrO0zIE#GSSgWTv^<-Y`%snd@m-}w(u)6BL zjuJ@@4L`)Gtgbo+&l$R%%Epyg9d{JCXKfSi&z?f-p^RTEF#iiI7yf(V}TvK YHjhS}Ql6mvo|Rv$AjS71o>Vhd0HyyNqW}N^ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c47cc42321d347f0b8596e94c53ddfc0c5a90a88 b/external/boringssl/fuzz/cert_corpus/c47cc42321d347f0b8596e94c53ddfc0c5a90a88 new file mode 100644 index 0000000000000000000000000000000000000000..2eaa4b215fa1fe704b5d64a86a769c5add509f9d GIT binary patch literal 33 ocmXqLFkoP5Flb`VSisE0$i&29nDMQ~YO;})0k0Jsr&gN>0EN&8_5c6? literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd b/external/boringssl/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd new file mode 100644 index 0000000000000000000000000000000000000000..8d81d37589ab67d407aa1cfca8a130cd38bffa2e GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxB0$s6aS8Lfr{;$gl@^yMc;+SR z8A=;Sf^20L7J`er=j10P<|sHj8Z{tHkx`;+$Ubl(z7NrvrHnJg!A^Zm2XyC};#>zl7#K0mwcdL6m` z1j|Ri%z}k2uf(Zo-?m*Lve)Rf1hYmEOX1Vi#>Lj(NZ#X!T#%ga#>D@rZSFD*(=E!HneEyyp< zEXgmbL{1dIw9VYu$WZoBD9_JZOsLI(ZBrx1`41e&j~CXZy*u>winaXz4^-ywX({a<%fO!1#}H>HgvEmluA5m`0u((A=CA{?IE xc0Zl?zS-=xY*_xOTYHL=Cp@XIwo^K7%lu0=6{M2GE1ORQeLjC{% literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008 b/external/boringssl/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008 new file mode 100644 index 0000000000000000000000000000000000000000..42c6db63ea6cf62a449570ea63decabb3ddf98e9 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rd^osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZtX?mc5#jLMw)^SC t_swRnWyA7M-P%)}JmE=wwVl#wTlTl{7A12YGY9xBTtDMo;-?mSApih+K;{4d literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040 b/external/boringssl/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040 new file mode 100644 index 0000000000000000000000000000000000000000..dcc743f4c4d47ee914817e2c657d4d07939c7f13 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhSIVqk7!-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9acZc3yv6lb;;ll~PYt9xM zb{f=5TnKGmly%xnaLx;lw8gpgJA|*e|Lcy5DgLwWrnHfy#p>xMBCDoddc9aigu`>& w?xz#qH=Dhd4a+}uYfo|VgeUdYc1ovh+26)nl+1a|9N@Qb{fu{spIYpN06)Y+IRF3v literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 b/external/boringssl/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 new file mode 100644 index 0000000000..eea0415290 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 @@ -0,0 +1 @@ +Ÿ­œ:† \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744 b/external/boringssl/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744 new file mode 100644 index 0000000000000000000000000000000000000000..7f767fdec068520ac8fcef04836f57959c3acc32 GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW&n;02xosmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZF1=nXBf{aiZTHiO t@0-nD%ZBBjy0xb`dBT(WYCEOVw(M`?ElTD*W)ARMxPHdF#7`~uLI7XUL6rai literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/c6bb980166717e341bc7628fdcf7e6857f42b78e b/external/boringssl/fuzz/cert_corpus/c6bb980166717e341bc7628fdcf7e6857f42b78e new file mode 100644 index 0000000000000000000000000000000000000000..9f4dec049f7a71270b5224ef4f91242e8755a382 GIT binary patch literal 63 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5MuRk}y-of~m|*jEqc7903{MYM2a~m{ce8KQ-WG Txtu~Lg z@4SqR+^h@+o`&28oNUaYENsF|p}~g227(|CmoS%metvpRs)A=;vZ1PhGDwhFSOzXw zl3J9PTB6`sT9T1plvz@#;BI6fC(dhVYG`0&VQ67$W^54!NzBYs2+K?@hr5dh*HCV}s})FXc|x`CX0j z3*{^LIj?6wL$%6LS@R7(Y7SFBf7`iew#DOyr0mx%)#u+V;xcMe(ti_sd2h7=13Z99 zjVKLZOfdjK#^NT%Y=b7obOTwS>t$70Kz`=XW@BV!WoHJu7Rq8W&;dycvH(NBi9Z+B zgG~aNc}e*d$X@0Kspe;4VP;})Fvx%z!^p@IV-RI!pbZgVH(+X$&nPJ=u+rBr$j(I4 zukY^Z=x(H!TvP&6%gS!R2v?k(lbM=VQf!E#hDssRtkRlg zifYt1R0JtdV39JA0BYs}1_le`wMr&dMgs;mw)93GU|KdX04b4Y(KJvuP+g$BKoRar z9A3&nOZ3c5jEoGa7U$+I^jjX8;Ir}H&R6OIyPn^deE3&BPnVHRKPdCiN#nPwZ}<(C ztCh}Qd-rgbiC~c5zr6pSqiUtw?r+-NrgE}#n#2`R!D5pFaGuk^m3bMNif$id_EOlI zCD#bg#)=LKizF8wxM5u>dn@9=Wrv%8x?Z?>y%$zpy8fzRZN-Hdnl;Hcbv}IUexdSA z@Zh2Y@h`;;4Vr*OLkQJ#^c!HNVb*|@I1K{eG>s^D7(gYD;MWDyO3-PU1s)qNdrtxKFGx0p~V&-DL1zPjP_SlNyQ+e8oN5}v0!UQ@uUi#wT@O(JgC$vY7gvh7g3yXruk!MfA9Bp-}m?OeV+vv zc>!F+cW#ov2|}1tOHJ^dTAvO+{BDCv$CN(t!EtXM24iV&=*A~gDZZ3QO`)YAVHaLf zFRjIroyaImW<4DWA#9M8_F;o2MlsfGXRKz%t{9nbH(0Djd!a%b1$}$^&@nVbX=qK1 zI$D#4mTI7*)WH4H!1%^eLXlT|hRK*^v6_t;v>arpRD(d|lVr(%w7a%8OfkvG%zvp% z#OdNB=xKkDbGk(0xfw=NWHu7_u#Ab+Tjs)4kn#oSoM(m+IA6%!khp*xg;4=Nf9vX* zJw6)JpWf+vvP9RErc3qBeYSpSEmqY3$H2FCB@P%-{&!n-)fbvy9ho`z78aeoU*#25 z+D~_S`s?DmTa2A< zkl^7U}; z^Hmd#-`7XCgx(j!)&cn&uKh4)h-9L!-TXZ4&$Qy+rPucyD(zoi#;IksLKUl(ohiML zUhUu5Lt-0}YrT4e9H-bjr*G{O=Lp51fQ@yRh86~1nNoLt#N~e$Hz$mHAlpA+!ch0YfvzsH7`52baU|03kmptZaAax>bgz$X zcko4jAtHoebY8wOE2DspK$b%hZ)yJ*5k(54&$lv)c*bfsW*PMvcIFi+SWG|^#6;0B zgareO2@PmoE@9N`^*V@v>iK9H3wQSSt@$=PVvs(P?hOHKX;SKkHap^4lO;35q=+Ah zhO}STv*0`oSwW1UxEH~C;>sz1J^cHqXGpI}CF$4SHfe6!Jj+6Tyd%enQ8AaM-e_UpV4=N1H%KqNYn=O(Qe_hNRIB`mc#B;jv?RC0W0J-_kfV=y_}F zaovS@&8})F28Vw`>Vm2{C)J*?K}wKRHjl~LH20$e(nf9jlC){IfG536L}4@fnI%Cr mUpNLxHi-W5Qtot}-_;z0S#os zjBhonllh-g63D`M0@)ookj+gEjEpb>IRj51XQt%?133|AAR9CoG%#trMR-a?q``2K zFjK|?M_?iXr6TO{AZ{QEi3h&&@^V--JZ}faLldJCa#%33GB7tW@-qO%xtN+585y>C zbiboiHDMvGKB5F7>1vnc;n=jtzXI|s}$2azHGKTo1(9NYX5fy z9%<&=>UM6on)v@UI<`8j+w-q?#nNSyLMA-ASaM8m={Y+if0mu;7av6~mae^-A-d_q zge6N2#O&g;ZnBG9Y-62c@t`>M$rZ0Dn>kTtc?^$jZ(!St;R_Nu4;daxTXFPVdO6`7O zG{gDq!HwO^L*);7&9<3Ff}qXFaZ@@pd4mlU;*Pc8Aw8cM#w;*36$R3v^cb2X&zMcWUw{t kheit{BTI}y6wv8lK93qF*tZ&5ng;*p7_hP%C^EGH0Du;%8vp1S%*;~=%S~4pTpW z+qr1A#p8yg?AI;T=ie;iGHO%Oe-nFoZ*|6^CdO<71L}vZ9GK+(;i&Bn;e%FYaoC=hEIJ2R7k4oF&11(@)Fws0^o z7&IYA@gh(hHwk3sCFO%1q4CzBsRB9rxk1|bSy-5v*c%KoU^Xx^vcwof8EC`!225@8 z86_nJR{Ht{*_lZC_1!%k-Hr5;i%O6bGr|=o=VYell@uEy>&Qk-W2|Nj%-(*f9FXOS#i^epjRXLiq}Q&g=Xv6phOl|TRB_#z``uYXgnMnHe-8~)Mjr5X>N(>N+8R3ePb23x&N{S7U zb>t@(7eM^L$0Eiea@g!y*W?^VJ?;3wXusg+_pPOYFAXFzJVf0fdY$^fdo(|7ceAP7_U__u`(KPu(72# z@&HqzfdNQ~Jd37*x`FBf%H*O^;ZpRD=y5? ztVzD9^Wkgv3zcVr2NxZPe<@}t_;tZF`ONO6EzTm}HrDDXPCc0yJ9Ezp#^t`-I;^g` zuj8$CiL>Mu6DsAI{-4KJH+&u|+mT?K=mL|z3widR=CtnmH&Mhle~(+hB+ly8rK>I)qPp<6Pqwx z4-1ztmwSGGx=*S?PF}L1s(~`lAZB41kXTNtf@fYyYEfP)%n`)efb1$1-;*AUrr3iK z5-8-j2j*k2?_fS=!SHg4f@5h(Mt)IdNu`3jk%62zuc4`-fsuuwg{hgbMHG;0W?*P! zW&j3J2AN0^vH=z$EF3&s&WSmhY57HYnTdvC1|py+W9Q-Z%`Z*N%qz)L2+K?@hsGWY z7Y{flpze||5CbV@=Hbst%*@eC2giqAa(=Esq=7ISJ1{Yvvt?pr;{Y?X7}=Sf7+56l zY-tit_cu0({_#@obe-STD8Ep?f}itx_A^wg9F;ZS;G^a+_4Bu#i)LFqZb-_0-BNx2 z%_1(NHYNQxv6uH&8!*7rDN+I?D!prHX)*vo#^NT%Y=b7obOTwS<7HJ@Kwjq1W@BV! zWoHID7Rq9B)&WTivH+7?6MrtM|C$6c^OEu_kbTSzQq9l8!py|pV2}YbhLMpa#vsbd zKpP^!Zot$gpHWg$V5P5Lke!L7U*Fx+(cMTdxu^uDmX+Or5w18nCo?s#q}UKyM}Bf~ z0mKh{EMhDor_G*qP0nG|(~b{}_Pf47Fg;-PRRbQ7tArUD|FbX|Ff*;MmGJR%tI%Q->SahH(0J#I)Clm!&xSRL4N=8{(p|Dm2SJgX?L5-$3ZSj z^H4dNwG|g;Xx1d()cNqW`-RFg!Gntq#J?0XG-v{vj=fYw@f`MI4`+sc1I#nb l8Vi_#3P447g8Pvc!8aV*EhfP&&K`x_bmv^Of83a2Iwvxu)DxcNH&x(5Cgl5hd&nc?=Qvuy6oodr)R2H^8C!6;zIZGpr1#AOV(LpaKS1enIlId#XVW Huv`NG2p3`v literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f b/external/boringssl/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f new file mode 100644 index 0000000000000000000000000000000000000000..3873f4b70dbd55008aeeb37b21934bea59703f2f GIT binary patch literal 991 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXMd@D1%I_R&nrfIVa|1rsWsqWhNSm8Hj+a zV&~!Y%`eR>NzBYs2+K?@hq&u13l|TvyCe+6!0zJV&rQtC(Mt!rST8w0*C5hBn2jCi z&2zR)jBFfW1~Vf&vl9c0RHyC8VOkreXi7|*W z(1!61nA+qsN=gc>^z{p}Gm*6GyL&pi8|ft%l^`i*gey+Y$xO{FDK#0PzAJ zix`W@VY6pllXDpLwBrM#{jM(%Ob=Ln)qn@&1z|?U|13-f3FHnR#5r=Qi^3;mWyCirapxAT>Hz^>=_B_HnpK4+&v z+h6%ST}C$jpv*%jjo+%i;Wt>WRyzOg;VcuuAisZk|3637O1ItLw7X5^Wal)AE24tM zCIv;e4>EfxY|WBubWm6%x$wXZ>q^;M5eF_i-2Bt^!p-Zw@Y3~H4Qned%+Rb!zNz!! zYxfJ4XMzV89f*G^W+?b|!8G~I?xiixBHuRF>M2e=nHM{A`5xaDjN3Y_uDY+|t#ygB z zPDnPCFc1T~i-$kg;MzU|rY7d5A?(|qK;M2>Aj-FinK^pt;Hc0`&d)W7G!SNE2S(~S UTP8*}4lS%Pe*hZuZ5|$N0I6b#)c^nh literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c b/external/boringssl/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c new file mode 100644 index 0000000000000000000000000000000000000000..bf18fc9cf8d39882fae70d04384599bce2879d05 GIT binary patch literal 218 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5G~pk}!~c&7g^C-vVYPMkXeX?ENf(e32)k4S3l& zwc0$|zVk9NavX`@!E7^}B+Qhtz!7LsBhaRRjBhneK$}%3^FKAzG61@cjgtdnR7q-4 vUTTSgV`)i7eo=NwrNaL2b9O${&~n$bVE}>#Ln8yZhPC3nhNgxFMiv$T|5!S6 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61 b/external/boringssl/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61 new file mode 100644 index 0000000000000000000000000000000000000000..c439807e2f79ba244e7ab01e11eee2f48b14ea8f GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxB0$s6aS8Lfr{;$gl@^yMc;+SR z8A=;Sf^20L7J`er=j10P<|sHj8Z{tHkx`;+$Ubl(z7NrvrHnJg!A^Zm2XyC};#>zl7#K0mwcdL6m` z1j|Ri%z}k2uf(Zo-?m*Lve)Rf1hYmEOX1Vi#iS!EUp1F;4Xk7pS_wJ&X&dfokovVwrW@r()cuNcUJ6!5W# zv4|X~nvv1l`Fk~M3Xfpzs@l{Yr_T5p@Pnj<85#exuo^G}DRBCb8bf8ph(qA&d&u26zdm*6HjuY9*}3?2hyv+ z;%?w-;LOGXWHK078(6Y&XtM#+COZ?Om@deyVxVE=<>jb`6{QyEmlh?b7V8(K7UUOa zmgE;zA}0!9+GcKSWGH(ml;`IyCe&uYwyBZh{0ENX#|!Jy-W_^-#ajOVhYu(Gt~pz5 z*lAEJaUryMQPycQ!8tEH(iZ2|?-0J?{;xYKrufggo6<&-7OSV5h^(4+>Gfh65f0C7 xyPr;c-)#0;HZ1?ttv$ub6Q0yp+bNy4Wq%uQQ8MQ-bAaE%^)ucjermB70sur*LOTEe literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 b/external/boringssl/fuzz/cert_corpus/d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 new file mode 100644 index 0000000000..08e5b85ed7 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 @@ -0,0 +1 @@ +¿ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/d51782b160d3dacee93a1dc34cfec9a7ca4a6c53 b/external/boringssl/fuzz/cert_corpus/d51782b160d3dacee93a1dc34cfec9a7ca4a6c53 new file mode 100644 index 0000000000000000000000000000000000000000..22311623707d6113e005413455bb038d31b683e9 GIT binary patch literal 61 zcmXqLFlb=Xcx%wa(ooREoUwpeM5MuRk}y-o0!L;hMn)zk4#OAUYM2a~m{ce8KQ-WG RmwSGGdQPf>XI`?Qs(~^{kXcyf u4Nwr~!Uh4bV-XHzKyfKpFUYwisYNgs=cSf>SJ>%T%21M#&%gk5?Op(ks74h4 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d b/external/boringssl/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d new file mode 100644 index 0000000000000000000000000000000000000000..ed27ac74271edbbcf96a71cb65cbcb2b4f05015d GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;S0>y>hnT1$j;_f;5Nr^cM&W;96j7rGfV6kjUNme-x|mRgHcwQMZ!R=LB!)(#!u}_o2FiOzoD!k;BP!*!u%@+vLFR~ zEMhDo2dZXd^mhJU&6>g^Si7n=b;qeQeg^y?X<j9K4kep0xZBp#b#gy zQXtP_Y+z`hzd(0^cAI8KNlAf~zJ791j$V3dehDa2^^)^*K?244#o)w~oTvxn8Tf(p zDzLa4xEeUKu>hG22G$0aY#iEbz_iKE#3-f28o%xgbO$S2NW)t*@)lkKA z!-N;`@L5rSIu_UjTSQgk{V`86Es0)eV@Xcf!;;CEr!TF=vgw%S>7CSMHLGY-o=6ay z>m6c`2*I!z?g@2=qcjYG7z}~&MM2qdl+|uKF_u&=soAtLCc42zN4>My9jDdFA9}I4 zSU9J|d}UpBLzf{z5*xs6=(0OgV@lE=H^liR*aku&l!0Km&`Vh`7-|YeK;SJD#M`47 z@m6EOAq#ihM0Txxe5}{U&ve5m{`Ix_&9#B$=)iDI=J&muMbq@YS4{^W_U}J-`_IPw z+?_#r<7)VGZaner`t;KJoGqB&8(6>a{>8L>Uq=bhQ5>46#3nCc#%x_YGMg0TXG;9=g14x7RPKcHJIKx=&jya z=NEADRmIJ_^Q*qj4!|_CMl*CiLgYNON1FbRI z{Zdw|XgHGJDwdK;EUit5+a0NZDotem`>r8w;(8fcy)m0a{;rEdqXQobb@9Om%V1|t z1cd$)3?^t{Q5&Hbnsc4{#JhJt-;keN{yFpX*?8kZbS40;tiVGWp@DWXj>Lynrmz`- vmFMF#c4{Ah)wGZfXs>tyOFO)PitWlj22+w4H?)^1mJous&{k+I`_23VFaGN( literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d b/external/boringssl/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d new file mode 100644 index 0000000000000000000000000000000000000000..7c91980aa23cd6fc4fb8bc49f161bdf6a77c01ba GIT binary patch literal 1431 zcmZ`(ZA?>V6z+TP?QQJ`wX{P%hAl#s52fdpj}_)JkZFejhBBO%`B9ond!^o%a=Sqg zQf{>IV_Bk3of*T*=5$%I=`uAa4xR1?+2ULjr*6h<(@r-C%M@_Qgxy<^)gQaR-gE9b z&w0-Cp7TNwf>`D-@I(;!baxnkM<1ki>o9k?6bBw}2Of)raZHL~c>I|NsL5H`p_fDB zYJ{Xx2~<%^m__2X1gXPnYpB@}CmIT!Y-v+~X>hbqiy%kzD0LZ2n*_LP0^FAZ9KtYp zV?VJXZp}a)sH2cbsg{l-36wt#sRJ#E^8%#8=JmQfw6UCZQYJ_jQE}a~Gfs~7vovQc z4RCI+pW#}KHVe$1qoxWduvjT;L1CWNE|`TtSqdTg*@1~Eb*zSpmZ~M>Dn*&Y!!&sP zEaRXOKrfb(snnI;0LwWT*0_qH-+U6RP>H;vy&7w1XTVPz%V%rDvdV63<2J?pQ*`o=%Dw0$?!qp*bLnTOV1Iosy`fJcqMBNwC!rBh9W zNK2kW3bP=?g;LWe3>J#NwS;g_yk^tW?D*LXTkma&<*O8!So=r0sT zcI@$>+?@3*>Z*PSYhBf!41!9er9)_vz(4{9(Ml%-)r0!wx5$K)zA^WSH%2>8o~chh zZSOQgniyatk|9yZR0vWK=vpf#MIa|hSEouCc>poQKxDxJFon~@X)_f6ryo!3zA2>= zoJUAPTQ7AVsyeb}L&fol-rpBgpZ@K3($9|#>>@;(S2AA>^!`sOh0zKJvVLd0K4`;-%)g=^5nMSLEES5_LtTbDHGxYs{NCy%0;hr zOUa8hi|c%}_f>zOIsfg;?2CVOZ9P4)OJC{jW2%?kZQD(U<3|qeuh4ZKNE%P+Q0>uV zbK$9kvfRLicbeTS}BJUUu-62D)WCX;Wwx!T-Nlyz3xvh#iGJ?W{9 z9Zg*yMlNpns5cVImS+e1;Vx*%S^eW(y^+l9EGUuy%3L>()f)OfepvjAiY`1+urLV6 cMuK;?XKK1l*L<#J%FzPbuziC+=lf>-U&o`j9{>OV literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/d7ba4e58caa05b0c3bd0f5258adf1429d022632f b/external/boringssl/fuzz/cert_corpus/d7ba4e58caa05b0c3bd0f5258adf1429d022632f new file mode 100644 index 0000000000000000000000000000000000000000..4142ca23d55ae5c40296dd32d49cf9047c074e27 GIT binary patch literal 968 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS3+%qA>c!tAbvrI~4o6^6P7+Cb?RZXp$rh(Uuv15lJpAviU;v?x`A1j=}=B}OLHc8L_)W>$`gJM&| zbpzga>NZq`ul@8cKKl|w?@o~)BBG`@54bI^E;=!B|H)A8vlph@%~4A^bN^hkWZ@~l zXIHLPuarC+dhf)WOK}##PhnVTCK${q^k`FV>8wHdH&>Nvq*Aj8tI z|9b;N!-gi727@N%j5#|Y`9zb$&>+M5TTLU!`41e&j~CXZy*p$8)nKjF^!AFi{QnOh zPWWAOw%D-KpjP5SX!D}1(`JHmUU;M}&aK}ee8v4=cT`OApLI8-jU+8rPd5=+HSN;t z#WErsp4)amo%p`l?6quIK66G2^Ql{VijyZisjpU@%&*ndu=cHioziJr_P6mCC37A# O^9J}WTtDL-GaCRCs#j1l!qCFh%-A9d$Tc%CG%_;)gD8VctX6UGa5*RDWTxd8>)fVIT%}7Y~1KVrGtBI@rZ}$@#ekkp{wS z>_Bgxvt?pr;{Y?58QGbg7+56lY-tit_cu0({_#@obe-STD8Ep?f}itx_A^wg9F;ZS z;G^a+_4Bu#i)LFqZb-_0-BNx2%_1(NHYNQxv6uH&XDn`F%rH_5jif}*S2!I?!0_Oy$aONgPMut?2bMqGZEssp_+4yhgEA@a~&+kh<{41ZQ z%gCl5lzHf+@mtk5{07U_O6T7_oMj>yG8JaEIhQubEFfy)jz|8%`@^Lj75bp2Js+KLM^G;5M?>U{Xx z{X*rL;K4-);;mka847+~Fik$QdufZa$hVEPdWus|=Ect3vx0HC@3s!BtM2P~YhB_j zxy68C!@n zCH7LAOa;k|%wW{gp%B6bN%0eG(7?#%8m)}k$XI2wO07DRS#Pb7siR@SSRXo$hG-S7 zic`j@GSN~AbhHxOzf90SwiI9Bm6&VL=bOw%eJ(8p2`bgW6ZoWHVfSmmUz0-xNKJb7mA-~CMuAF6(_z1eIbMUe#02D+iw;5fAeres3+PymRUAf44(oS;w?7wJ7-pis}9rH+o$nyntm z_;9k;pl6I$3+?%YNoy${JcKVLr6fm{t~cH_;8Ec@&u3}AbBYSmws(Pml_kdU2NVGq z1hK0S3U%EknfD`CI=-b}xA&zx_I=HH;|^xp6%foO$f$APkDl~Gt)TGp6$A$dK9^fy z7a$t~uqi>59HxK`Y(!WuI4Ij$2dQ(C5{ZpoFD7)(S;(;{*FR0y{|bRD9Qv-X8-!d4 zb%r>DhtKps4KR!te3aYaqyxt>Ms;T6X3dtx%aV5wH2pRu?clGM1FrlVWQ@eQiuw8@ z?J>QfH-xZda_OcYj~2#?=4%Fw55oS;tQuc)c~5iAr1sTrwX9ZXV70O%rRCG_`FD;H zSz?RL-ybID$@UgbXuWHnDVrLwx$VNVioi>Y+PYLM%b2NBwID2i8eaOf5-i za+rawuVlLQPQP25HlTi@UM9FZgrW9>4P6~%73#5T@Jys%vumV*IC3=xnn%ZWH29+b z5D|j+Y)Pp;KewEYM4m$tZ}Fsu5m`E;Ej2T;M8<5@=j*k(R%V10EG8ft;-YDYWx>E= zLItYfCCq-b-XIZBJs&k=av%N$bE(CO7^ID&$3p;HniTt?&B3_ZV9Lui$P#CvDV^wf z7Mz12F9tfI_vUN2G!LP`TlZwXUpab$@jJf!7!tSr!Svb5m0hck>UKaoJU&?fGd}sFL@b9N@l^lw`?oWozr%JlF$4tMX zYUU|d=G9mHCWYHMZQ(s7MOW_=B#z;Y_CB!pJ~G^MT)O+==l0Zor@jy(8=V?c_s*tH z4^*_hT&H_;_21h$FA79epH(pjPM+4F`5Zz82S`K=w@U(rEISa@a4saU2|-j0(4cTe zI>T$^gCrY70J7m@5Ws(kfZ&G+7}a{WUZFK3)H5b4>jD<`iY64XC@gNzX>$<-4WMC* z$tX3zj-hWI4`V+-$zuEa&q5-XLfaTjgZLq|61X&y6=XqdEh{T~w1Szjm`crB#-cDY z#iq3uz13u{@bng%6Vh(SUb^CE)I2Bks{!sFJO6AS|M>Be>inBWdON2DJ?QH@p*f$Z z+SLSAVDs1S%*;~=%SHfwB(LY|wov!n{8s!(tSMYOQ&whq#m7}ue8+_Cp zrhfjmbJ1*z#|=r@uUo3mzgfg()TX5WCie2)>WsxrjM)ZFjOhllK&xd{SwIfv&}L&~ zWo2guS_Ne>8R&qd1zCVW*M#o6CV|Ynr2GnG_i}?&^Ruupu{RiGz)WFeWQj3|GSG(c z4Vc>GGfGMdtn~E@vNMsi>$`h8x*O>w7nL9>W`rwF&dE&8D=9Wa){&oFTmbO`ABz}^ z$YHZ*U6XSd^|a#yqy4Tg5KIqPebs;mfV zv9;`LYjj9hB)Raw4eLtTTM-8?JKX%!^}@~Tz3|fYR}E_`F3ixZNxrG`;cNE` zm1lwn7afRyDP}16b-^_G%N zD&?8}pT}1>d>$*?kzkwX0+YTAdG?>?wC?&hQN%ZYk6XZ`>eQ#13xwX!pY9{vI8*Yw nbRCaIoKl{k{GOFx9`U4_Z8g;?NO$A@YU&=9P^5jan0Yk-w}v=4 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee b/external/boringssl/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee new file mode 100644 index 0000000000000000000000000000000000000000..513eabb402148acae8a674181130f51ad4d125ac GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#W|Ro7#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZtX?mc5#jLMw)^SC t_swRnWyA7M-P%)}JmE=wwVl#wTlTl{7A12YGY9xBTtDMo;-?mSApivgK;-}c literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/de05b31a05846f00be753f15be9242b01396a553 b/external/boringssl/fuzz/cert_corpus/de05b31a05846f00be753f15be9242b01396a553 new file mode 100644 index 0000000000000000000000000000000000000000..1c253ccf4019a0d8c03247ffef53d81d60d40125 GIT binary patch literal 88 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5MuRk}y-o0!L;hMn)zkj)0tRHB1IgOsbRlpBnJ8 naqj;<=iW07ElmS;1_K5Ip!Nj~Ogs!tAhtD-YtX>J02BlOX15tB literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674 b/external/boringssl/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674 new file mode 100644 index 0000000000000000000000000000000000000000..2f9537c0640a73a1d3949dc842d6579b5788e20d GIT binary patch literal 986 zcma)5PiWIn7;j$EBum$JHe++>W}TbtkG9{-{!kUcO{5OyRAz;BdgwydJlZ8QOK~!l z5~L?j%1(-miFXfPhUiWnM9_oi$(uM3=SkS~q%T=pTM;p*_kH=^`+dLf`~ARS--Cmm zuds+gNX)Hs=R;F3rym;eeZDBYUe!TeA$!j*b*;-L!~(Et*uIqcwFb4KK48Sw?AZaB{{Fe+)y;`_>4{Wm z{>Ovc>%OI~7wv8^1Tgxpn0vT*83fy`zW@nH%@GXc4)oQY0qYQfT?KQ+rHvqa6< z8kN_w?cWiYt1eJrNWn1Z>d94C0ut2_M(YrjvXUe@nAFS*R$;+*r5wY1pv}c)(8ZcX^Le#VPXNoFdmdrOqh$$p0Iq7D;R@JLMN`C-&h0 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e b/external/boringssl/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e new file mode 100644 index 0000000000000000000000000000000000000000..8363e7d91c748d38c1dd5ee9831f38cfcb5c3520 GIT binary patch literal 1838 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}-84NrPxeYkkm_u3E z446WL4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG{Veaqw_CC+1|P1S%*;~=%S>+gJuKfj0MahA`OO)BTMNqJO-UJ6-2@HOeoPui)pr zp8X8fDo16_H~6SIO#S?A=c3sbj~kM*U$<1Bf3t|os7*=#P3+~p)ftPM7_$wU7}E`8 zfmX|^vVi={q0Pp~%F50RvwXv6phOl|TRB_#z``uYXgnMnHe-8~)Mjr5X>N+61@7z{uT zGGK(OPtM6q%_}K3MAnp_TwDP01|N$Ui^yTKXI+zX81=N{1Ec+}FAz)*Sbf!i2jnne zM#ldvOa=@F@*tiv3ozUpM7-{@iAnGIma(<$YvZ=vNm9F_8ubknK?)RDqzoj0I=O&> z!NPd0l8KekfP;-Ky^#kPy9NdzCGsqq2I>Z?3zQcq!kvi2OF2jho|TcCfw_s1ks;OM z+`NT;%OewfHvZfBN3ZSj^Wg-$Y{SK_TUSnW$J-F1vh%f`H7vQi&1+ofTgk1m@(*_L; o3_t>FNsfp)>=B1IR@RbP7B6~Z)WUVX8l^0r$I5mj*e1FF0LUE_7ytkO literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 b/external/boringssl/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 new file mode 100644 index 0000000000..af531320c3 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 @@ -0,0 +1 @@ +1‚ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/e180125371c88bbab75d9aac4d6b1144e0f0683e b/external/boringssl/fuzz/cert_corpus/e180125371c88bbab75d9aac4d6b1144e0f0683e new file mode 100644 index 0000000000000000000000000000000000000000..5d77a89acbd4f765c11188ff6683cc7715368cd8 GIT binary patch literal 31 mcmXqLFlb<6WMFA9XkyM-z|6$R#Kd9HV4z{uz@ToJ@eKfJ5C<;+ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945 b/external/boringssl/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945 new file mode 100644 index 0000000000000000000000000000000000000000..1fe7694e842fff5d1cb063cd3f5cb0939a336cce GIT binary patch literal 1766 zcmXqLV!me3#I$b#GZP~d6UXcQEP;HHC!-B`**LY@JlekVGBR?rG8lLoavN~6F^96S z2{VNT8wwi;f;e2lT<-b#={~6nIeE#3ss_p+L1tkYkYG-#f@fYyYEfQliGpKkNk)EA zW=W-jyODvMIIp3pp@ETwp@pfLu|*V+Yi3|*WM%*cQ3jbWO}a!$<2Ov^9I%S<#B zGY|nPMG z^A|WY)uExu0twB$lElosfe6jd=%H!UrlkKS_VV89jKxii*#=FF=?1dEh?G@j0YyKD zHX9==D?2kV;-D-h10A+dSwR+H&^4h%H85Igfoc31B#ko*?S5v8l)ROI$=eT}=8l7s zw}1g3D8+CIv%40S8fY4*|JOLgV$j6W05mBBWC}AAhhfII`D^FwtWllJZw1UPp3vNq znU+{#sB54N($6id0@M!@Q3y^=E-gw`a84~M$xO>kPAoBKFlb=Xcx$i-W~hirgW)7$ zri=xSK=VOaF(Bhx4HMAWsfg?Y$~y)|2Bt=a1}31~0?IoU1{QFxffL*x;Mj&_6QDnM z-Ba^Jib{)1fO#@m&rsSx5}YH1h2Y}uIr&M6IiS3*;OqztYbE3ofKii`fw_s1p8+Vr z#ni;e$Z+e7M6$u(FXGBlVRg~>ZE`H06mGAWcxBJR8$Lf)IB#Qq>8r@j(Qzw6Kh08e zFKb2jT#Fa1+q3ElmpnU?ux!Koh9{jG{PR?=y>0$%)V6ln#N#tgI!Ty{%w0RfZIWJ_ z|EZ7d&IiS&hU*5r@6>Im3Sax_U3~T>hTfebKSV@LZys=4TwQcx;{KDN+Gj6Jx0|Du za_0WIX34@+e$TF4tzId4HuTl)^A6o2YH)~0nQ)wz@@Fo6$_KU*oCqJ2(85tNCH-0c^d}|;NN}$Rtz#^wX#N%1U zPwh*are1fyp{yX_Z#-kd{40FXC{XM$aZradPWB%tr^>F92xmt0f=)XUxg)6EFiot%@InpaY6h*bLO=O-5zAce-CFjw baog@Bsa;Wx`UZ+1Z3-+>2CNc5Be=8yLF5UK literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 b/external/boringssl/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 new file mode 100644 index 0000000000..46ac641d00 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  (€0†*0À0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/e662bc8b0f1bcea6081c65fc1195e6df53a51961 b/external/boringssl/fuzz/cert_corpus/e662bc8b0f1bcea6081c65fc1195e6df53a51961 new file mode 100644 index 0000000000000000000000000000000000000000..21a90781e722cad05411de6f903c3dfe8c77a0c5 GIT binary patch literal 1261 zcmXqLFlb=Xcx%wa(jd^poUwpeM5MuRlCVJ&^EHDerhN;TnHZUvII{P%1oB0mj5gq9 z zPDnPCFc1T~i-$iqF*8Rm9qc&08+YLs6nU%}6LJ^LA|RgTJGGfGMdtn~E@vNI7TZ`619baXe;OD-xwQp^ZfoSc)HnpaY6h|rO% zpPyV@0P!6kix`W@VY6pllXDpLwBrM#{jM(%Ob=Ln)qn@&USUSY|13-f3gb}D#0x3YA0t3WAb%F8%MYx}U0l>NcJF<^p zVUUAJ{hZ+B&)mew$dGDrZr(z_<&g>B`F+WUf93OZ8QJuMG7p_JeyjS1 z-(a~~>HNEgvrGho{Ql+r*Z3S&E8TW~)9yBvlbv7(gYuujB2fMV<+o%G!)X#%L@jVZ$%uq>~Ql>*9$kV_rgopUp1_)xG+PrCV9?H zoey8TU#L72Jhs%cGtqv%(TP`LtS7B1d4DAt3X8*f>V=Ai&7Pw iQ;SM6(=wA2OHvUf3aB_SFfuSTGBhxO6d=Iz!~y^b)Ov{k literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/e67cc75ea22aec3e31ac08718a0e8ebb49d0378b b/external/boringssl/fuzz/cert_corpus/e67cc75ea22aec3e31ac08718a0e8ebb49d0378b new file mode 100644 index 0000000000000000000000000000000000000000..e704b2b930fa3fe248af08eb504b600b9acf752d GIT binary patch literal 13 UcmXqLFlb<6{6B|bLz{**03Rg;m;e9( literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/e6d0bda14de5fabf61d6a77ed9de9dc32751c193 b/external/boringssl/fuzz/cert_corpus/e6d0bda14de5fabf61d6a77ed9de9dc32751c193 new file mode 100644 index 0000000000000000000000000000000000000000..ce4f10335e8d2d911d94ae7a7b062988e3879bfe GIT binary patch literal 25 fcmXqLFlboNz{JDQWWZq1U~SM~V9>z802BlOT(Ac0 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3 b/external/boringssl/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3 new file mode 100644 index 0000000000000000000000000000000000000000..93353a7a5de1bb876a88ad0877255da7db8c966c GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxB5cgU?x9?~=Th@Sib{)16g=~i z^$evABtf<^3k$i!#NBi9lM-_joE;6C7?qH{!N|(M+{DPw02Jq9l3-{$!^n6m+2HRN zab>Bny6F2hITlX}w^vNOvS;B9pC2onw=uu;Rb=PrxD}zFW~sTCwW52j#S7N$S#^a= zo*hY8w&8ullTHo(d8*gmHh*5bY~t}5C!HirMdq%Z;WkOn|J28J=YwKX!*v7Rcj`7& zg|GeeE~SiKQgN_Nh#k6S?{RS?FDqWu5iS*Djx*U3R^W zTz`V)qhDsh!j@O!)U1t!!hZeip&03P?RK5~3_!56W`$b{) zlb=k?#~2tFH-0c^d}|;N3`SXH76}8f1`&^E89%izZJK)B{f4rFfWPsK3G=TQ$buB` zv52vV9H^R+(cAfZHERlwVC|~f)E%eJ_!;nnq=gw7|Ff_fFas%Y`jF)Z39tYY6`O$- zNP#?yv4Nq1{sP?v+HIN{B_#z``ufR5IeO`-`6Zx8)l1IL1ql@E7lRW|a-trPXW$3Y ztH9!J;A-H^#sXwA7+4!vvT4#7U!21C8rka7o`^D z7iX5_7gZuB3Sio1Zfs;IdnlCW=Pf4GX27mUaj^oD*>(bsGdV9rM{{M#$C;YBC zTWr{AP%CjEw0Tk1X*0n&FFeu~=hp8KzT*C`J1VC5&$^q^Mv@k*r<;hZns({+Vi^$* z&uzP(PJG{N_F6V9|J1EL#mN(%)K}Xnowj9v8*foE=P`4D-@^4X-X(r&u@?dWYKcPr literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/e9617db6d8b651b46ea1ef7b904887d3259d8721 b/external/boringssl/fuzz/cert_corpus/e9617db6d8b651b46ea1ef7b904887d3259d8721 new file mode 100644 index 0000000000000000000000000000000000000000..0cf5bc73130a8035a08dcebb9f14fefe8ea12d85 GIT binary patch literal 62 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5MuRk}y-o0!L;hMn)zk4#SLZHB1IgOsbRlpBnJ8 Saqj;mjI68-27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9%sv*dePRY85c_!DQ}aWLN{dSrJoA$E z45bYuLE_57LU3{SocyH390g}bgC<5Lgf|!&8Ce;an;7{S8Jf5ZnADpX8E&1CNH+NU zMO;}btS8 zRpDzty^GJj#L&A_CFRfi>r%HOx%AmRQv3O>2`C}QqJ5z*DP6h%J12gtJNzd z&xYPR@#a#TMex%Y{~q0c0m^27(w?2}TVg56uzf0%(8XO~^C zBiEl``RJEfu(0KoI5q9twkt&T8oica)(B!Le7f4$_MydYcC(hGIhC)(48Fu4(0);v z{p2STGb01z;>HgKjc*O)fx#%N%pzeR)*#~XEaRv4rAyWdb&5b!siF=74{16hy) zJ{B<+kpopTGI~3IuVzi*5v*NRo4VuF89xJlkhCx(<9`-b17;uvP9L)TAORL&qGB_! z0x6JZF*YzX&|jdtK)X#dqokz3N?$*@C`T_nHNONDsd~xzxgddJ{bF$9Nlw%Q@(lby zdKFmQ4O|VJ*;s%~1_NsYOEwN|HelLhXJQo71({V0G_1V59M!O*)Z+ZoqU6+K{i4)@ z{Nl`#{Gv+aL;+0O%#Doq>HFBK)z;XO|VO`q0LvOEG%m4rI;e_8c zXNwIx4QeGWgf=hAI&CI6=Y>bw;@tWj!dKk?bw|Y%|5h=FRnsoLUMwTR z;kj-1(~0k!&0fof<)6B>r#N}Sllp2qrPH?TZ{saW<~(K&@LRZk#=FE%E%rhHx;sI( literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229 b/external/boringssl/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229 new file mode 100644 index 0000000000000000000000000000000000000000..a6b757b1155058caceb8ab146c437de2c667c9fe GIT binary patch literal 1905 zcmd5-`BPI@6wX_+7?uD@BdACeQ6NIj3z7z`PLa`Is{y5G1uKU5Ad#2{$wNR2O@fow zs%_DsGA-IDj!E8w^>OV;|GRt5ANCm=p+~i3^)pO-j zrry_a)Q%W;M%xq|6Npd`+NKbgkeJ3JBYxWB8eWu{1bGi`j6PYT@5t5X1eZMAw5F9; zHSW8}=XcE-|6={!-j*#NYJYPS6yI7|b*5{JSnVFG>U!;m!&Rmx7gh`|tOz0zoX8lG zD?+3cV0^xiK&b{-I85Y@LrK(5mk;rJ$u)E%qSpIdvpMLl5VN&_sqil*fOC_OB!LSZ zVDiPoFmfT}g3`AK+#O|N*^*S1s-)QL=daSuOw*|ojW*WrXFtx=4swQCCq)fQC2#^Y z46&ygwaYue9wO|Z*Pl3iL>#@}ZRTWCArQ>ng;*+_URq`@G*nOtC>^o{NXHFY6xp<~ z%tkBHX&Y-UG#d>pJxCxkTgkBp)R3&EU=qg{jy+n?4sBuDv-t*zB9;c}Xyz4LnVsdR znn;a=2rerj4I8rSEKGsHqDW6ecQn?&42;hsT$qH1>|)%7VIh}Jg&X1Vz2VU#=GEj~ ze!-%>TDq^IuKm#F3$q^Fn7uun*gHljdh61ws=}1G!~BZX8@1Q@`6~AVb)8$J z&AzrUb4@~DR!<`|9zOx`5z5ZQ}Ql{119(Ph}*+$j>H@es^)ouYYT@ zr77);#w&lEvR!sqeJh-ZolBNpYfhSSMSD=FSy|9nc~cJe@{cI5mlj`rh!Z>vYjXC0 zvm2r~)58-GyjHNM=&QdmptAkUf}`ld>Z#8cb_f{nN}BW%bJp z8)Bl-Vy3OEo${w6W3-p}Ie(+^zP;XpC352A)F2TIYrWst;*E`ugE(dWoIL$`PiRqA za|Z-+h@=?ygv5adQK?Vyz4WsHdAQ{x5A~Y9SpJuD@4mf8E_aIqFGI&oO;xx^`FpG*ZQn@=XtmFHj3q zho8-<-LmwgCbaQ-Mq$&kH}*^0b$zRI7yciohW*i}7e}fiw9OkP$#x9BdW6HlbMY`9 wt!>-1S^x2Z#k1h^zLuL4vJU)yIpWIWC~LygM==KzsIn>f+<}J)&71fC1)>l^6aWAK literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ebb2f919adba543e9f61ba5ffd13e89c9422f70a b/external/boringssl/fuzz/cert_corpus/ebb2f919adba543e9f61ba5ffd13e89c9422f70a new file mode 100644 index 0000000000000000000000000000000000000000..e5497b5eefca4b021ef978ed9e2fcb4af37c0f3a GIT binary patch literal 10 PcmXqLFlb<401|5f52ph@ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf b/external/boringssl/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf new file mode 100644 index 0000000000000000000000000000000000000000..8ab90f423e8a8737892d461b146810b3a0a0298b GIT binary patch literal 112 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5G~pk}y-o0!L;hMn)zk4#TJ4YM2a~m{ce8KQ-WG zRl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a#NiU=a?j6C&q-A{pO}RM}IVx+u!AH$u>gR7e7tOYK+>n(0x~2O3n?+nkZA$uY zVlVHl&RE>Um~D{P#F%a%3$$BSl?CKr4sA9@R#tXqpj}WFlYtIMT95@8bWJGE14c_N zFj}5LqJ>##_cP=eVFkvBA0(JqLfMXkVno1z59CWOVRqNT(#*8P3PW83ZIFnt3RFNL zI5oMnC{@8ZwWuUBEi*Z>!~m2eR=hP>!~(Pqo+6ks7B~VE11L2FWPGb(0y-lV5rd%U zGcYnRH8M0X0Yw-n`Ya4A;9LVI)aZl86qhisduo12QE73B0x(ka45bYuL9SyK76OWc zh23-VlM-_joE;6C7?qHH%gD;W+{DPw02Jq9YGPz$xOGM%+2Ai0cdAb2e`>(b#<~Cd VoSm8)TABuSU&NKA!s?>$0|3YH$W;IU literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22 b/external/boringssl/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22 new file mode 100644 index 0000000000000000000000000000000000000000..dbc33b6f93efe6a95dcb1e539c72fdbc27594af3 GIT binary patch literal 1088 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BgyC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG`83-;k{eXW`)Ca!$<2Ov^9I%S<#B zGZ0~8wq{}H;q}cg%_~XF%u@)naNu53;)?48*|h;^EKC$xYNt2fJ7=IX~AR z(m&MN6lgC=Wja~&9->lkd*zprTYAvMO;R0O8ReNFYm3+Slq;zZP3J+ZXgS^ zT2_?>DPDnbaXe;OD-xwQp^ZfoSc)H znpaY6h^!+&xmXM02R;@t7Lmhd&$=e(FzRW?2S)o{Um%zsu==V256D%*jEw(Tm<$*U zBEf)psQNEt`~b#ehif`#!~B@-*7 z0S6mfdLs`o6&e_Tl*qGa8mJqnE>K>e2zMe5|Ky-0SLP;0Mut?gbMqGZEssp_+4yhg zEA@a~&+kh<-2Z*fPJ_0;@_D+9Z2Cc&hfW&5Rei&6uw1Ql{@ue_CW1kJ|MLESj;fVz z+qAn)YjjXpB)Raw4eLtTTM-8?JKX%!^}@~Tz3|fY zR}E_`F3ixZNxrG`;cNE`m1lwn7afRyDP}16b-^_G%d>$*?kzkwX0+YTAdG?>?wC?&hQN%ZYk6XZ` z>eQ#13xwX!-`_UfN4RmOJG^`0^W&l41 BO^g5l literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2 b/external/boringssl/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2 new file mode 100644 index 0000000000000000000000000000000000000000..ca67e3cc2a6b3e20aafdc2e5d6204c6eaaecda09 GIT binary patch literal 1624 zcmXqLFlb=Xcx%wa(r~_sIb#8{h)9FsBw>Rl=4%E`O#2ovGchtTab)jj3FM1B8EwGJ z#;Mij(e|B}k&&B~!NAjy+klgeIh2J>m?<>aP}o2a$Ps4Y;&RW=PtQqJ@XSj#R5efr zsbChCfeV(T7UiXuC^(juWaJlRmQ*S{Ffx!6=QT7nG%&I-v@kU@wulnvH8M0aFfafU z22lo?*sNmV;Ni+j%*jm4FUreIG!!!s0a?Y)!|R)0npcvTnWqqznOY8Y7Yh#;*Kvfq zBn-sB?&9IkP0Y;EO9#v7CFkcFL>dUQu>-w%&X$RhjRVYJW@Kk}VqlTHv!zKq-QU&F`;I@!AH$$>gR7e7tOYK+>n(0 zx~2O3n?+nkZA$uYVlVHl&RE>Un2j8??%0AB7^sFupwI;Z)S%q}i$ze-I^zr4Fa@Nb z<>EnhJR)dws1>vze>)KJw?PwQx`8Y(R%KOLKxu(Pn~jl`m7N(Fi%=GmfeuJokOi13 zoA^^vUDqU#nU|Dbft(b$L8|##SeTjE8w@gF#xOFn#27?b8EC@<44B&FGfGMdtn~E@ zvNMqk(0BKAbT`sVE-FD%%m`PUoRgWFS5j<S@OZ zM*Ce~AebJo`lXaLK|Ey^V5m2Uc->_aliu?!V{6&h#%;Tkq;^F$ z>KiD66ezGr8At$iash*ah4ES?6Dy+u2OC>@BM&f#8yJ9;$g^k~s2iv*P+p)2av~n@ zH)i+->4fdQgS0_G@qnZ%T_z!6v+F)|h1 zKFI8)ur*7rk%=Q9<68}rL6f3`!Xn9q2X0tb%HE1NaM|JJpRN~fUhjofm#)8RSX*&n zhGtFjO`Q*4yI-h06Fj)+K>SNFL&2{Lrpae^FKuxa`L?lEPjTwWyx5t0RxmF2-PU1s z)qNdrtxKFGx0p~V&-DL1zPjP_SlNyQ+e8naPE0kXR!48*|h;^EIt%*@eC2fJ7=IX~AR(mLHEluL-{>BE;KVHh6uJgMZqvcwof z8EC`!225@886_nJR{Ht{*_lZC_1!%k-Hr5;i%O6bGr|=o=VYell@uEy>&QT);44VZ2t!#L8&E!N!)}$OBA;24H{6 zvuGNq8>lW&UZ4nfA`buLpd?oo2IeM4Mut?2bMqGZEssp_+4yhgEA@a~&+kh<-2Z*f zPJ_0;@_D+9Z2Cc&hfW&5Rei&4V9>-|3(N)2Ai029X!kQ@6Iodq4E#`2rGNn+&>O%E zz`k6qbpGALStf!(e*g0Re~zk^Zo9u}cbm$|&S?@?Ld4Yp;?oBQ|H6i?iVW01P?Ac5dTulQ1I)5 zY4VxfOIw^>3rjQ85-SXK4YYw4a|^3L1r&l)lS_+I6`WIxN;1dCy=nR`|+F8AHmVRhAg9dE5moF%uIP$|#!|2)3B;lLoqTF^8x dDuKe9myMlM3tr*?1KiVq8(RJ_vNA9m007}?Sv&v$ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ecac00e857f10a143e5760a8d027498fdb46cbf4 b/external/boringssl/fuzz/cert_corpus/ecac00e857f10a143e5760a8d027498fdb46cbf4 new file mode 100644 index 0000000000000000000000000000000000000000..540320c89650d4d613252543ea9f08c7efa32ae7 GIT binary patch literal 64 zcmXqLFlb=Xcx%wa(qPccoUwpeM5MuRk}y-o0xM=FW=19^j)07BHB1IgOsbRlpBnJ9 Uaqj;h6V-$094}>6#xJL literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53 b/external/boringssl/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53 new file mode 100644 index 0000000000000000000000000000000000000000..cda1d18cd16f4fdc59954cb46ad67ff9b2182d14 GIT binary patch literal 1177 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhV1NM9=_Xv=t?0=OCFa3^f~QVM%IH zUTTSgV`)i7eoG=m_wV5k(HI58E6%h#blrZk``nEMoSaA>zV{I^OEu_K<>pBk`G7> zNni>9`lZGZTA*K?ckzjEpQX2I^4;+AskFrZ)MEl9B=|ef@&$Or${5clUI3 zH_}TkDnU}r2v?k(lbM=VQf!E#c*-omm}?O6y2~aez2{rT*0QgS+jb{O?TTvDH&6sAP+*ZV zkboz2NDBG2W+O0#s6$f-3nYc)l_Vmi5TI6g3IW>71&j<9#%q;Ktc(U6Y;27@z!rZ_(LxTk$XA8*_XMAk&z+Q;@rH2e#;{hd^Y~u`AR)t*Yo?55C6*N z=`ynE2W1{QY5Z384S&IMwbJ=_4`-PO2KoKV`>*jis#dz~{-)h+DknR^t_8W(U=hfz zpz%H*O w^;ZpRD=y5?tVzD9^Wkgv3zcVr2NxZPw|XgNDEM{3H2KW#r7h0j!bId70InQS%m4rY literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100 b/external/boringssl/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100 new file mode 100644 index 0000000000000000000000000000000000000000..3e1f378330f38895cbcf048d210e9e83c16714f5 GIT binary patch literal 1244 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O`B4Xc8#|hO)MY@s6kCYlR|(x_ALM!0W=|dKT9BAHe+9u_WP zF8BQWbe~j(oV;X1RRd+9LCnH3AhDcO1<$;a)S|ppm?J2$0c;w~1{P)+s1-;?TcHMs z6$#D<8jf&23x@kk6dX%SGV+TuODYxIjSS?(c@0es4U8-dElkafEuw&2GXp~-GXpS) zGRVXhx-1+#T+WF(nQ8e&d6|iZVg@3>kh;Lm!|R)0`e)<*%shp#%+zvFRJZ}-g^LFq ztWZx&7>EHCvoQ1U=j7^TCZ>Y}S1&m~*C5hBn2jA6v*&D?7}+?$3}!}lW+w&~$vaz` z#MAwa4WfU%lsjGLcQwi{l&|3Dyq^6G)hb72%{Ta{IZXZhZReud7LOZ}vR}7UpMSH6 z%cxCB|4r=Wz110un;5eVni$g!WPw)8s;xvfW&A4rcQ7Ga)X@Dk8Bc+B6$D4 q1;7Y~mj}RfOO1SNfSHdM5X{KnR0c{=xKddzB3Gd%WoVfr%mM&l13=FJ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95 b/external/boringssl/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95 new file mode 100644 index 0000000000000000000000000000000000000000..14f5dc7504638a5622b4f3b14b243b5f0b23c018 GIT binary patch literal 1244 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O`B4Xc8#|hO)MY@xIsXpLV#NKEdZJUG$MOHOCVq5$!G&!uqq9( zbplA%0o7jvsb}NVYV&CO&dbQi&B|clX~=EB$;KSY!Y0fV8f++RAPD4O7)gX47A|2f z_x${HpHzjMyktXF17)B=%)&Atv7A%|&%BbJLnAW-Fo-h9 z#1^SZRTgTq!YIX~AR(m6aY?&C@IKT{MMs{W=1{TRXTbjhv z{f!Nxf4r1CUFUZ-$}g0!;OD%a{S4JAM`g`7_^3Hd{rqj`qS+RY8)B&Bn;e%FYb53d&+K&;dycvH&B#i9a_n zGe-~NI+Qd^Y2pWYwMif|FDbtQWIQZYAxFyt5~Br}IKctP4RSs|vPm?G;Qjj+03(>% g+1LOx8!sT3kHM)7l%Q~>vRp)_LQTrhB1f170PF-npa1{> literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/efb28c035f9c8a62a312dfe83434cddbc51b4c8a b/external/boringssl/fuzz/cert_corpus/efb28c035f9c8a62a312dfe83434cddbc51b4c8a new file mode 100644 index 0000000000000000000000000000000000000000..3c835e0fc7fda26e84d32db119befd70734c5d06 GIT binary patch literal 1382 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhV1NT(BgyC@-}{!LhU?BfluKq*CF5 zk%62zuc4`-fsuuwg{hgbMHG;0W?*P!W&j3J2ANo`;^5(OPR#kWW@Axarn;e+fe6Sd zb{<~e{L;LV#LPT}u*}qQxVw0e-6dfl26h(@e{N!Cj$S(0#d^v4xdxF2!ffn7Z=SPd zVr1h0Gng6KnVlF|B=2l#5>NLxHi-W5Qtot}-_;z0S#os zjBhonllh-g63D`M0@)ookj+gEjEpb>IRj51XQt%?138hjKo&O;g#-PNXU9oi8q>u@Z zE|wgVTYApU$e(3r`o%|)i=}ICW{7V3Fk#7312Mb!tefm27u#6pSUf0BeR9QX%I3*W zH?b*;T>1R`yyi*Y;+;{#h|!0|Y*Ou$_H%y{6=5%X-7i z(|eYig|sg?pcQ&~Vz}M(<{6LOtx~&R7|n1#dvIg-@=&>AzDE5mv2z|CJilBoe}h&+ zY~pgJ?R&Cc^6p@$I5q!QL9hHr?Ij}(#cn~n)10@D7VRqNTNCQm+ z_5T`&SP(vBVq^xpW&YYZJ3$%23TT`sw6w`gORO-|HP8m>=N49REi46zCY9Sx2P9yQMW-{yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zN?@YkMoQbvjg1Ut4~6plyv2mt4A?d`a-9Fbar}5;UD~@tZ?9O(|Nrpegx@u1iw!#s zY9%g&HZRILZ6-M9g-6=r-1;5DSKR+~N5vHXS$9*~NYY~UbQ6(P)2v=EmJ#9b+_wAa u#P`i+uVusXPu<#6oIK%4eYKs^X9y15{EnGk2UE-$}dm#V>CqU@{ literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44 b/external/boringssl/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44 new file mode 100644 index 0000000000000000000000000000000000000000..0b71f42cf95feb42c3714f08b1868302b3cdf53c GIT binary patch literal 1088 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%9(qRRd*^AhWOxT(BguC@-}{!LhU?BfluKq*B4% z$Ush<*U;3^z{tYT!qm*zA_~YgGcYtVGXR4qgG`83-;k{eZ{gtKa!$<2Ov^9I%S<#B zGZ0~8wq{}H;q}cg%_~XF%u@)naNu53;)?48(x$y2s4JpP7@JsFx0Qv0ie1 zu0f=MFdMs8+tzcoOpI(CK>wbzWoBe&c4Cmc!_u@xJl)^eAo|BkxzlxiSEKww`3io{ z>)Fpxt#VY>e1ngg!_?2;b}pK2@wg!=`*ln8`8SKWjM|j+-^2#*tS@OZM*Ce~AebJo`lXaLK|Ey^V4ydMc->_aliu?!V{6&h#%;Tkq;^F$>KiD66ezGr8At$iasfkvh4ES? z6Dy+u2OC>@BM&eY8W@0-$g^k~s2iv*P+p)2cOnk|eeZz0CT&;Be-NRWXfEfxY|WBubWm6%x$wXZ>q^;M5eF_i-2Bt^!p-Zw z@Y3~H4Qned%+Rb!zNz!!YxfJ4XMzV89f*G^W+?b|!8G~I?xiixBHuRF>M2e=nHM{A z&kDxnzS}yiuDY+|t#ygByYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EaIS$9s(oSxA`ts{-Ba^Jib{)16g=~i^$evA zBthcL!a{Iy_niEs#2f`@M}sCtC1h_fvNA9?G4eA2#krW87#Rg_osmd3`1?g%St_h9 z`o2w$#goGA6%()QS$Mowf^~aVUEz{vM-rB8 zc;E1(Q-gn=>b1AcpVuy%czni5Cka!Lxoc;*P15r}^|9UgpxD%K-GKLn zRWmYrJAbccP2mx&T~(X99nfJ_DhYXeI*4sAAI+GJ;96w?KnRSYz&yu2LMu%guB{L-T2)MEXj)Pnrt%#!?~ zO5{WVOxw(jjSOWEh4TEo#e~`n*fuqCod3Xa{CHtq+Pgz=6OmQZtX?mc5#jLMw)^SC t_swRnWyA7M-P%)}JmE=wwVl#wTlTl{7A12YGY9xBTtDMo;-?mSApp-PL1zE} literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741 b/external/boringssl/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741 new file mode 100644 index 0000000000000000000000000000000000000000..c3a681d4553fc575ec2ee8be94c56e9c4eea781d GIT binary patch literal 888 zcmZ9LO-vI(6vuaFr`u9mDrr+b1X{!jE!w^MH!ZtOSyX~C z%W8Tso*Rz+YavK-1io=!dUhc$* zF{lidJ87h+4^gD%&4N;uIMxP3KR-9TxD;NAga<0pzhi5t0?m2k<`^Mtj zjo=4)B>DBqRm)LVQ6KLPN%2UR$DU+d$sLK zqT*DFif1ez)f+M7H#OLrbY%xGjEEOX&6I0t7D8yOmw_wRLx`M$2(%Vsz*z?;N$C!s zFP-E|@_nJ6u8`jw%Sa`MOWw@otvAC?TUB5kG^RCReFb1>yJjrK#|3GOEiEj@#?t>h zR}ed~Jq@f~ok=0DhFSAvVaoEGHy77hJZ^Be4)+g*U*{?leRo&Dq&c!8^oL-ez|o;b zO+>v-*>>bDqh@67J0ERu_s{*9dhl?hb}2IDgGMdINot{5%{Hn?30j@NIs^uWNlcm0 z0gM4W2ETU9LEO*`E{Z^|Dc87dVGBzv5f@Y5QJ<%-2qyL4r=Vq-QYb{lgUhqG!gmJG Z^uj&&;+N*WrBCl_-v4$8`w-(h{ukC2@t*(y literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8 b/external/boringssl/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8 new file mode 100644 index 0000000000000000000000000000000000000000..a84f9e280731dd2d25b96212e2f56494d8364b6a GIT binary patch literal 1224 zcmXqLVy-o4VtTfKnTe5!iTTd%X9m1%oLX%jZQpqr8Ch8w4Ezka4LI4DLs{5_nL>jN z1q}E=94=vY*TT}ww8RQST?1{92)D2bR74>-HMz7XRpEbXQAuW6W^!Uls)A!_Nk)EA zW=W-?oH(z6k%6g^p@E435JZXd8d?}wz_|uasP>5&h(PS)bx+L?DJm^4QSi)5)-#kg zkOYY{3k$);-E;Dj5_1%s9Sxcom5{x`$jZRn#K_M86z5`UVq|2vbw(oD;O`f4WvQ^b z==(M~7EcNd-~quX!~_fpng@gdjRL|77(x_<#P*7bSN1Ht;qzmK^ET#}zKZM|9k(L% z(=0XjvQ~7@wRpk0J*%#8$+IH~%Qn1kc+#oCKTq}A+vd+}mrXoA>smR>5Gu)IW z>G_}f*zSB#Y-+e}!23?!hN|$jpWel1Ut;LpDe^-^)b!>7x5d>(CnoMc8LEBu!gRYi zYAI*#pKF#ZJmvT7%GK(Xl4nEjop^I8ZvX!|JKHp@ErOrM`1k1k3s5%ullJU%-x5nn zhV4_CEGKgF{j<=!D9bwQo3C9yKfCOD9l8Dl%SXS=f`u)w#HnfDwp}5z*XXqbvqlh0 z;nUT|wht|KvzxUf&8d7PX7B|V?bm?me;*|Mb7b#l3FM1B8I7EJxPh6#6E#r^8wf%Y zC6{}CetJ$SC`lTs8YqKPq>Kzu(4fJffl1@7K@&>@(29%&%pxKU@sos^G8Q-ja~d$K zaTq@RR>K6eT6Hr2Q=oMm`@hfG`K(Qg!-N51U`c9GUTO&<<0w2Z0wozkQ$qto69Y>l z3qwm#-Z3+}Y57HYnd*kX92Jj9?ci)Lgpt}oK4ItK z_02EMD@n}EQwYmUEjNUDn+Mt35(Z*mZ}afyCT8a7rGo=RFF8NgAksjXjU8B&oU>(O vWa9ucm>Jobofudo5v9tVEltD~EaK_@#=znRR=7BW3m1dvAHeeErQB%%K3r(n literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/f34b279011e9a03e95b85f6a8d5e2a59089fe516 b/external/boringssl/fuzz/cert_corpus/f34b279011e9a03e95b85f6a8d5e2a59089fe516 new file mode 100644 index 0000000000000000000000000000000000000000..2641dad74b2d657ab220a0542973eed2679ec699 GIT binary patch literal 1160 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf?MoV;X1RRd*^AhWOxRM0c8B(*3nwM41l!qCFh%-A9d$Tc%CG%_;)gD8VctX6UGa5*RDWTxd8}RM}IVx+u z!AH$u>gR7e7tOYK+>n(0x~2O3n?+nkZA$uYVlVHl&RE>Um~GI+m~J2ov|3h`1>|53 zZ8k<$R(58fRZtd_feuJokOdfYP3W#`63EO;%CA6nFE>avKMM;p6MKU}2Fw^nMwS=@ z^(X^vn1BIOn|ww|Nr9EVenEC7k^%beo{sKDddWp4NQxQZij#9PQ}arS4Uu)^Cl?n$ zJi*5z#v*dq>{-|397a9u_`qnt>k9piVAeP_Qswt7KwjG~i%kOK;=>CPM=Q zkP>+oO#^j<27?ABjkg9(EDh(Im@^hIi-`~SLy+~p5K>z_*Xtp zmyu0BDD%)s@jVZ$%uq>~Ql>*9$kV_rgop zUp1_)xG+PrCi$k$hp*i)RGtYQTy!Ab>ZO>W;MWDy#(}&zK*xnCC-vt4Cn?91_rQ88iY!DrvK;h)eWD=%625!CVI|JO%1IAlfDai z_Mhgo?)o=T#5aGBTY#p49mAyR)TfyXgx=4e4h&CVSXzNYhyfV<1`R-REvztLX8`3; zAK}KClHaB4cr@aa@&x7gto&m2h$q!-tEo;wx*N9v*mg*)8DNVw111jSX!~mF4gggq BW2^uG literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1 b/external/boringssl/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1 new file mode 100644 index 0000000000000000000000000000000000000000..d8bd910a159f1d398602425824bdc6910e0eeb4e GIT binary patch literal 1396 zcmXqLV!me3#I$b#GZP~d6G!%bmO#G9lhFpeY@Awc9&O)w85y}*84NrPxeYkkm_u3E zgqcEv4TTK^K^!h&F8BQW^qf=$&%BFI%0#lxSQn3x$`H2yVitWr$x__EpVY>K}6sr}y-c%+$ctJ}HV zYU2Ob=-BG8ZqL8o6-$>*3YqZeV#zVNrRVI7{8@IUUwjm~Si1IRhUlgb6P7GB5VMQV zy2&nbv5j?(#e?G1Cs(|tY@Ymd6PvQgmCw)5n{Ib~^OF7UgFUCCl{>8D`s$c|ZEx1= zpB3{pK;Y8{+u2vwYf5gmtT)U&y=S>uNc(~VTA`OGhTBbVp7Ge-Dz*EC(G2Ia2RC*v z50xwCYt-KoJLloS^UL+}Hy9+uCN5{%z9;)7?+%8FQ}cfn^vZwKUh-iXQ_&Y?(+3qY zlD16Dj0}vx1mg`15_d>~QDp(8a1L!YMpjmKW?ug;-Xao|h)9FsBw?nE z1&+WB49dZv#KnYLzYZup3bFw6Y74f_3^~%2fJJ~GJjomf z6#)VUe4q&D5@vTTj5N?RQ2(!Shy~#;CPrqkTjsBwvlEoqt$@aPLQ9m)w8RQST?1{9 zer{nE*TPbeh(d5`a%oYjf^%w7NoHDRa$*V0vx{K42g9=gAkPAwor)-8KuO=g$iURd z(7*&#qJWaVg@FZ(+hiaK2>~GkfhOd%3MvmW*t8%4&B(|SV-N*&AvE9(nA+qsN=pi? r^z{p}GhxXas72r1)6v~XFS)1$Niic(F;KS?Jix$ZCbZ1r5-tG%yHb@z literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b b/external/boringssl/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b new file mode 100644 index 0000000000000000000000000000000000000000..304f5b3ebd06b4ca15b3d19172be54983f950e9b GIT binary patch literal 1927 zcmXqLFlb=Xd27(b(qPcUoUwpeM5MuRk}y-o0!L;h#zrP4j)07BHB1IgOsbRlpBicz z0M)Z`a_s*;XXi65O`B4Xc8#|hO)MY@xIsXpLV#NKEdZJUG$MOHOCVq5$!G&!uqq9( zbplA%0o7jvsb}NVYV&CO&dbQi&B|clX~=EB$;KSY!Y0fV8f++RAPD4O7)gX47A|2f z_x${HpHzjMyktXF17)B=%)&Atv7A%|&%BbJLnAW-Fo-h9 z#1^ z)BTMNqJO-UJ6-2@HOeoPui)prp8X8fDo16_H~6SIO#S?A=c3sbj~kM*U$<1Bf3t|o zs7*=#P3+~p)ftPM7_$wU7}E`8fmX|^vVh#nq0Pp~%F50Rv21|%>!f&I)4vXLLzBpOA@{(TEzQ348n>urM>RHyC8VVu6v7CB{HK%0L??V8GNSpHWg$V5P5Lke!K?Ui95P9o>!e zl8Z`^6f?pVC+B3Q=9Ls1BIzJ8j$kDT3x^KQ#Qt;R{{7$Ki5+{$k{YDU`uWMl1(3AL z$0Eiea@g!y*W?^VJ?;3wXus_a zliu?!V{6&h#%;Tkq;^F$>KiD66ezGr8Au?!1>B`F+WUf93OZ8QJuM zG7p_JE_kc@hQDCBTIu||hqFusgZ%#G{nz*$Rf}HyNVnZr*|fXuWGC49;A(CWsG0-S zOUWFD(MH!ZtOSyX~C z%W8Tso*tZ6}#;>nn^SB!ElXwnvGwr;(!D96%bOm=op$h?$J$dk^X4;rd0 zTn7if02k=+w+F%`^aJPfLwl}87VCa5zY=at(C!SIU-GnazqfF zCxqC!qAs&3Sdb9qs==PuWwwq*grp~)-|-Au6eVdR>hCD!|>0~4KFT+R>Gmdiqx;Ut2y1&?q~J;@AmCEaP9lX z;{5f%2W2$z_43rq^?8#ov&*}F>eb^Z{+5aoprSa`6FK!RteG&jF-WgB(4^JYjDo$| zb|oe_)q>(#>ql}U#@wa`Ta&Kt5X4dGe5sjoEzOECO&Jv63-u7fCm{@Ng&3%egO}x0 zr`MZG2qpR6U~hNO=ZU7}lEWo$=F--i;bvF@tdpi_4Oo937%J9`CWV+Nk8`DkrRaF- zzvl{U$F`^bwJWnp$4gUVwAJY#Wj@B-Pr@hdqr8sddRFiBIL5k7pB&A1SWSIE0 znMek38-3a-2X2LCaOp5)o3f2X2ivH)>k3?w+x`TtC^}V#bg{tl+|AJKq0@bE@6Y0w T=KiHm?`q!vc8L2B<308d5K;0# literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/fca0bbdfab4ad790670f079ac242c12a5c7fa58a b/external/boringssl/fuzz/cert_corpus/fca0bbdfab4ad790670f079ac242c12a5c7fa58a new file mode 100644 index 0000000000000000000000000000000000000000..ff878240ce9ef723f85fd1a043fc95273c2caa31 GIT binary patch literal 886 zcmXqLFlb=Xcx%wa(qPcUoUwpeM5G~pk}!~c&7g^C-vVYPMkXeX?ENf(e32)k4S3l& zwc0$|zVk9Na1%XUoLM z#sLhZbGFQk?95IKERuJ&G>NDC8yiIbcqwuG znVgfEnpaY6h^#$7xwru0Gd>nE7Lmhd&$=e(FzRW?2S)o{Um%zsu==V256FqajEw(T zm<$*U#og}p@s!`uS5u`|gMan<|sGAEI zMl6iiDw$Xr4LI1?(i?eziQ2$Gi^B+{N}fg2K;1x>B`F+WUf93OZ8QJs! D^=R?0 literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac b/external/boringssl/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac new file mode 100644 index 0000000000000000000000000000000000000000..2d3b0ce0af4ba0278056432191466566534b0a0e GIT binary patch literal 897 zcmXqLVy-o4VtTfKnTe5!iCJj(GXq{WPOUbNw(q=*jI2@&27ZRz2Apinp)72|OrgPs z0tS2_4wo>yYhh_-T4IHvu7Ng4gj-kzDxwgqo?Kd#s^FYjRFavNnVeXXs^C~!l96AO zSyE{rC(dhNWMFD!XkcOh1X1F=h86}EMutZrTmvUm`@{@HAolUPr{;$gl@^yMc;+SR z8A=;Sg2b7Hh2Y}uIr&M6ISS5>22G4g$lhQyW?*h&-Ma=!X?j+ zBrMzTzTruy2LC+OYj2xBuU$6r_>7ZI5~d<^*UoU8r00L?W4rS~v8my@0q;9?8>+(B zetO5S^HO$iyvPp`QPZ0T+!j|CotU`)WT^Jp3)Ai9sHL2_f38`w@RZ-PD_5&mN}dh9 zcjC>ZIE&z?G5$Te{{ocF{-ixS-M7S2l41K)Cd-N3eE%%;F3Pgb`sQnw&(AKqUPrD! z!Sc~BvtVJ%D{*Stw{2I5>@|8V!K@L)QuuVWvF$^P-Rx#9NpmV+i5Yx}KcM}BIlJ&D z(-TGp#>I^v3>x1W$OD5>R+&Y@K&(N;<5|W}?Ms`cUU$EttRUcTJY&NAD+aP41$-=G zEFuT0W@Pks{$9yYhh_-T4IHvu7Ng4gj-kzDxwganp|3xs^FYjR033yoLG{o;8kjUNme-x|mRgHcwQMZ!R=LB!)(#!u}_o2FiOzoD!k;BP!*!u%@+vLFR~EMhDo z2dZXd^mhJU&6>g^Si7n=b;qeQeg^y?X<j9K4kep0xZBp#b#gyQXtP_ zY+z`hzd(0^cAI8KNlAf~zJ791j$V3dehDa2^^)^*K?244#o)w~oTvxn8Tf(pDzLa4 zxEeUKu>hG22G$0aY#iEbz_iKE#3-fmwSGGdQPf>XI`?Qs(~^{kXcv;E?AOUl$Tnf;8 zWFRNbYiMd{U}RxvZfam;6b0m(85kOw8Gu2QK?YWp*P zzm!W>DW-RP*=%<GnD_&DJPky?IO$`$i9>Tiji^YGyL<$C!W3=(1!moshO zll_u+2SdfF`M(N!%Hg9;f*TP9{k2FArrjNZT?aW{|!2Bxek3n&UW zwAmP0S=pHx;VdSD27?ABjkgByWF;cfU^q#bDPw^nFonUA7?VMhfh5QrK^7qcfhOdL zNe0G92FyH0MwS?ZC|8BE}*z^_0xl-vw~Vc2UmLgWPLkRc)u?Zv2vV%TB4r=}G=)o> z?I|M*lW&UZ4nZ@6Km!S{!Y-y_kbYt?&#A zOtFj%X5k9!?^iT=?{A*L$aeeK#{)ZZH}~wa`0RF#TdyjP(dm@t1oJ>v8^#x#f4p#- z$gL_kCHCu{*Oxz-S1vxl{PVNi&BWze3mb)QYw8=m>uK2ZctOk)=IN6Sr?@Ep_VRdS z`H)w7n`c^XweIiCxePiA`M3_7#OBh!ApmVwqHF*F literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/client.cc b/external/boringssl/fuzz/client.cc new file mode 100644 index 0000000000..a90a896054 --- /dev/null +++ b/external/boringssl/fuzz/client.cc @@ -0,0 +1,55 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +struct GlobalState { + GlobalState() : ctx(SSL_CTX_new(SSLv23_method())) {} + + ~GlobalState() { + SSL_CTX_free(ctx); + } + + SSL_CTX *const ctx; +}; + +static GlobalState g_state; + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + RAND_reset_for_fuzzing(); + + SSL *client = SSL_new(g_state.ctx); + BIO *in = BIO_new(BIO_s_mem()); + BIO *out = BIO_new(BIO_s_mem()); + SSL_set_bio(client, in, out); + SSL_set_connect_state(client); + SSL_set_renegotiate_mode(client, ssl_renegotiate_freely); + + BIO_write(in, buf, len); + if (SSL_do_handshake(client) == 1) { + // Keep reading application data until error or EOF. + uint8_t tmp[1024]; + for (;;) { + if (SSL_read(client, tmp, sizeof(tmp)) <= 0) { + break; + } + } + } + SSL_free(client); + + return 0; +} diff --git a/external/boringssl/fuzz/client_corpus/00717d11ddde89f0895bf72de8de3bf99d1b5c46 b/external/boringssl/fuzz/client_corpus/00717d11ddde89f0895bf72de8de3bf99d1b5c46 new file mode 100644 index 0000000000000000000000000000000000000000..27985b43e1acd8a328297271e29f7504b070cb1b GIT binary patch literal 3954 zcmeH~eLR#|8^`Z^?wLWxyD)@7DsMAqriNiNlJZtwO7g5)(llm9!!R>8FOeBiHbf=r zVcFG->M5lbTXvI=N<>?!rIv)IBvPg#rRSdMW!0zW*?nIAc>Z|q&&=m@&Y5%0eVuEr z-}gF~0fIno7zp|TK~}nYxe+_cQyzrl`3JHM+Bc2 zDGP{n`+B>cWd$+Se9HpH#s$=HNWFh^$+q5 z#3T#OR{2S0>pF@?^Vt_9f(deaHq-N#RBKY=zInm1y2+f1{Reie$m_i-zF@Y$jY$i@ z{>Zu7`(?RFN+)-E)kxmH{lI`39@VL$e>D?V%;*uZ``dkYo!oh^3U8&~K6?KOy=L*F z0hO+vx|UT|TV2d@Q!y`V(#hNRu6`D%{dC0juQw`fh@;M%sJxcCgN`eedfv)Itf(r7vT1 z%!BOqjU2!T*}|bM3?M3g z*1_rmZRw|e=Dwc>!`Rgz6xhA*1ItWvu2>xFLZQU2=S}%*C|*A9UNkaGD4sGI{xF%v z=dokNBI?u?0+uNDt&N&k1FU{Q^NeQ`&T}r!NVzs&b2ArCElOSr2nrkZVE7Fd10Z0o z=viTnfPqxsw+nAzQumzu!`IIw)o0ckpAMB!fQ4cL32O|D(3R8BGh^YKi5MIVRPlI@ zgn;S=0L2t@tPPkAtjnxq79ULf2j}5W4LDR-Xu!dcV+g78PJ(pF+4Le9fBV9d`r7D| z*{2z!o;TIWNn!B9W}7^xWw`kdPL4fTn6GZFv+Jv8b%WPOoD$3Hk?~Qp&WMAy-$`_D z+fb;(*=bdMWvlyxMmy?dSSYM4~}L`Ek&Oz=t|`?VXpR<}M`T1IaTan$wE zp3B^HKlpFY_K#@}v@UyPY(43oEigVe7CS!Dduq;!hn+s-VP<{H{FZ$gqctnv{s7PE zPEkcc7qjm5-r<1uI_d%)`}a{v@j+*M@1>J9w-UVOpY2tLWfU5TE#U>=~O0HV_!mFS_; z=As|EGu=7#ze%}2VoR|tcEjq9z&-U|Avf3<$Lnk9N zYG{kH%EanH0m1v)q-zU?2fqxza2J=R+ZeXXt!|Y!Lmu>ErfedAV0z;fd60(O_f_eN z?v$U))(f`O{}O0E2OtY>sfw2IH&wXIKj?(d{b`8~b}(gTw`}|sHEv?pjWwfW-^zv8 zS{^n=8CP8n>YBb}n|Tv4!o0Plg2}SWp!3)nO~mt_mSaH$Kli2iYG1H@bh?nFbJ2N^ zHnwaeBB{VS+kbg{Z}pIBv;M0#%czt7S3HrzLL{~RM0axK;<;B&GvjKy<<`~>8uYA^ zk_k&P~KPq5-@w;2XLnDJKk`}qQq#{I%OWvRjgNHK^5T9ZO|+U=x>Eh z2KKe?oDf`1O50P4< zIO#)S?Wx_SjhlL`@zD916Nj1{qEov|q-=W$YhEOCV0nY;sTRtM@I5Y3#eqqiaoH(X zZM`$DtMNBBw9-pQrNhg+x#9iLH-@C$FKlx5`n6PaXEtdFR&GI35Vzl6CZ<>r$D3Rz z%f8OO=)NOvyLFq>nD0`^>Tx4o`&f@vnrNfnJaSV^-c4<@JsBe7*r!9mn!|?phn!*B zpnVrd#qIgFhS=^^knD`fbw^`MKL0pKj3y1;%fClI^DvAO0Q6PW;7$3U-4rZd2__6sNGk>K0TbGSk;I-V)%6Mh! zsyp-fjQ+Tqg#7lp?>d%_Rd`e*1AZ1Ns#|aUg%as(^Aj#%TM6R70Ljot+V_@m z$L+3F75wVeVMWpom|K)r+CD}5pGAX~LU2m$;sBxszfs1=R2aA@CYWRA0xF=CIh5ID z+Po7oDpxXxEf6bmhXMm{)htp54=X~cW`D(664nbW1|E1U+JwLt!1+B*FtCAxVlNST zeNo;lr*0->iv;mP7F$FSvSS4zo>(AE{3Ny!i3Ixku5OI~5(C{#fUlCMUKvrncrh+D za=2lr{R{IqBO^`zH$51~e*`H;zXYd$AJyWhQ~ba?vOIcItzNs=QjB@UjE~B$3fGTg63OwB354irevmNi>t~|I73|AhXne6S6MV1 z@ifCt7p(?hKLP~%AZY7P*B14Z&(#*tzffC1hVIxlnDYa)^Ly;ssIj;sQIW*QG*jy^ z74KggHnR>LsqIV6+HKSsxoEHMQ`dW1Nu?pH2)AB$xS0MqJITj)5<;K;)+uA4K!>8W rwp_bmb(m36n~@~{Tv_wBWcvKE{%1-i@c)wOKP;L4dG+e@nez4TN`6Sq literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c b/external/boringssl/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c new file mode 100644 index 0000000000000000000000000000000000000000..4a6fe546939526480b97ca2cbf9ee5b0039354d4 GIT binary patch literal 674 zcmWe*W@fNtVqh?3W)`iR)+yE_nD6?&<^ea$9f#@HqwG0l@4r)i&$;it!ltzh2ecU& zco~!#82&RdFfuTRGcbrTGc(@hW?;O@z<7;;@v=b^<9Q%1Tfof3$i&3SaMOq7mS^q$ z*9M$y>{@Le=WJOR4O|Vmfn4TL7B*of$52CI13?gngNG|PKQ~o3xFoS8)lktu9wf-c zBjK4>l3J9PTA~o1nUbDaQmhbAQmNoml42ky&TD95U}9tpgodW(QDCkqoJ%chA`OJ0 zPG@3d;{f}CnUS5@iGk&rcIKn~sq?4r)0g9&(&ck?diM5}a=dQ8@2*@aH}}r2D8}d4 zrmx_V_<8uqV!5zKHO(Hk#iV4u%GQ0HqU(LWNa^6>00Tb*S)ey%`B=nQL{_(4TC;lU zhbBL<3ZYQ<_$O+;O&7tTAgjzGVIbCktbjc<9IAi^q+ghY)qt6i@jp^1GkY)?xH2g+ zd|F@{7ieX6xT$jXJN1Cpz5=$Aso|G2OBlZF6K#(@!p@{nBUdSsrP%zTswAWGvdGL? z8CyP{o+ldjOx`FcF|PEa2rz~jN_ZF;3YZyW6+X=6s!U&8X?Wk_^7$VP^0!a0A-=9|#zL07Qepo@d{5my6G9`MmSgp+Cv0fe8pq$uOG1!vBbNdZL`5L!L=yrdK}6+H0YzX%hr<|>U?h+P6%Zr=QARva z5p-e1!2@*_6$co_5m{6OK|w&k0p*G}phQJM+?Oa0TC+8^RZ}(lDyi!3^w<5pFW>*y z{TU(%X+`F9o-eN7SuC0`-L*|bG_RZvl~W){|04{+ z5M%^FkQMsXfG{v*h#*9D4Ty+?h!_Z)0%X`EAVYY02nNPr2vpviP1bw0dx0iieP*gh z>RU}1*1$o)ld1vK@rXYbuaEKfqv``)WoLr^1b3m3E8vhkBiU4IV5J;H^e2BAlyF3m z90|!aM#2+{_>x$XI}Ml{X;SG_Kx0xJ=zvBGLc0t=r7?i&2?D%7+=@V);1(v}hYLlK z{4lB^Fi>u#M$}v)jER(l@gqqAe9ne1ei6s}WdtUw{32>?*sy`jRXI#%3)cY|Y&rft zVH||WU~LE;pMa6UFy!R5?SP#Gj%f5U`k~lzc4tXO1>2IR@1mdv)@HQaEdE)s!6a@9 zcblS!RlA0wS$*X#i8u+lKb^I(O{P66b=@-eOxfs;f}_XwEZ^N#FS%}hw2npd!T!Rn z?^=;RDWR1&@%+HdU!7M2&i`yGv@t1i+)U-ylpSX*-hV|`$mYQd98qMRs{sI~lYe+|Xm)770uW{V`_Cc|GQvju!k zq(n>|Zy{uhqdxhlg*C()WL8gpJ?uE+=H!HiIa*tIaAJ1+Vn9^-s1L&*u^0dW3uVs= zYYYsN47}R$hLg(P@P1zZT3UQ*wdutmDFsYXP9R}TfiY@10expI+#HL+!GM6rbEQO7 zF90Z~SYU0ybYPulC7<%e#sBg?g7FE53JXm*7-9sH3Lk8gExMAN4dd@$e_39-t|y(N+hHkg&f}t?$MZ5YtabN&|GMni-2sQ#{Bq>opm}T9@tKFEdiQN8 z)V}nj^WAx?dXTKW)P3`U$2i2X+5c3I$~-)>Y6Szy*d>2ZlLSJjB`(0J>LbJcQ0MCbVa20G^yP&zQcp; zg3NYS*@uIDK8|b>M0EQwD>}~(Dg^fbZ3oHT?JR2&_B0>czRUIDfY7Oz-$z| z-LS(O7sY&7-v0Kc*=fP~lTiWj-G_E|r?TaxIwKIGKoK+mWSEvu7(y^k$=?JD%=;P( zp9wHQU(=lL_M37;=}*y8I^mge%(B+7K#!o-KWuDwjFo6;9F8m3u7 zo1c~^(eU%}KT;=Ko!R$nMacC|T#{a8@IIHal^#rm-`lD3;fyB}D{m|OG!m zl@X@rZ~3)PT(sSy$|TI9Hn)JqwoRe)IVn{p*A`k1`DOmvo#dr+edhCvStQ*Xjt6wG zc>`f_nbzsv%VN5UUl6JdM(Qjhio9+ZBGZIz@Xnli>ug_DJ>`%TwL8^`5Ccg-7 zOzbeL-2BiQ4_%u&e4@&JU1CSBjAJKd&kkojSyn-~P(yhea=ZELh_UPur0gAr-}TbmsRm(&z=q*iGP1GXXwh|6#9V-u#BysL7eEM1>| z!*x&eF6%mnA+N=dRevR2=gdQ^B=M#tv&mJFyPI{)52T1qqh7u6*XlFEKjrq(p4qi? z)m+|euZZec3CS-_y2~)N6bR1J=LvSJJMVq6M%_|t3;s}rc*^3Sr@ zyCfekdmMW4@cvr%XkgI@qZbdg1<^75@UV?kd-Q}rM>O=OejXwDao8~;4#|xplJLX% z>@W%E_X~&;0e}YRG%AV#^id*!37B8He+g#(O#5xOjM?CW!pO=rAaUh`IRa)+bjiky z#DnzS~tH) z9z1<4<3{$)dB${u+|$_$_mF+6Uv71~YM2>l@7tedpA;8(`c+@Z+6HLHF9t&f6X~tx z3-jYeRT)=q`rFpt$ztV9TXX9{U9w4ZwYR*nDgJ~>t$#<=^M+uiU+*fPbo)_XE5=B; zyk_SSM-!+d6XTenp*6}R*PG!EzFEQ&YO9$Q+L`YPb?kc2@Y8o}44!6t-?_lxGVPf$ zGGiGwy7$y9=T7D&HAc$noY<#^KoL@I`#5@S&%4js9{|!9UuoY%&U%dy5rG z$7fdd?n8~^wEu@_&{hggrCl6A)Zve+{1^`dC*=eS>?}Y9lsx-9+f46D1V$B|=f`H@S^SrO^6Ly-4pxhI*+0e_l$sJwUi|BRVm>ui{1HcNQN92CBT9 z-I!;80SU%;{F8r*sA1^lJoX6BU$?nbztMekd(bNJ$eGqjG!y2jtl0)9_cuJtpKL(z zEWXs6(VxtCW)>iF9rsL` zB({BMaWW&H-AfF5^;@f)iNX_Fr@ghI$?7Dtpfn{;fjPxS);E6Ox4m_!JM&=cHf(W) znQ7VNGbi{1rMvE2H|UR?{~MwCc5d(5`7Fkj`lo^3!BMz>?Yc17UU{pt=43PHZ2hk? z{@UVF?Yg2gyn4jYgKN`~;gMsz2>WURz|>w&UdD1k=()he#yyv~dp;b#*LB8zsim-! z@NW^;z1%Ig-&?mQgXcD|;;C*_w$^3e$L)mxjOT&4YymS9BNG!R!%ZKSTb{N1 zUmI|;v1_$?oU>(NG;lTK26CB0S=fY`977F-4Fo|P4j!)H{M1C<;M|guR6|7rd5|C% zkA!DlNorAEYKcO4W=eWyNwGpeNu`2MNs57-IIp3Jfr*hZ5E`1AM}fJfa4tS;a#MAK zOA?8*CelC{>U1VXHV&{Km>Jobofuf2X=gs#pE`f~K7BdfDP2BSr)O_pDaY&f`|iq> za&zzOieh|zZTbo>iJym$ES3vHT;rh3B#9tqV2Iq*qIb++^GuizLncUweP8Z`tYou#5Gr;!Mt`N*{i^ zoyC6dLm9c4{1*aS*ET%vGWq{@h5X^3xi^_|zwZ}eVP_zXAqZ@D#nRq$!2t1kBry<<{{iC~nl?srUfDt}?;6us*EcJ}>$1d~|LG+L?r QZ#tj48RTvjJ_ZH`0Hc)t!vFvP literal 0 HcmV?d00001 diff --git a/external/boringssl/fuzz/client_corpus/01e050c8b311caa72bebb132b9fe98e22ac56682 b/external/boringssl/fuzz/client_corpus/01e050c8b311caa72bebb132b9fe98e22ac56682 new file mode 100644 index 0000000000000000000000000000000000000000..ef1c9d4454146b5fe3a0bdd33c9d735958f60e47 GIT binary patch literal 3955 zcmeH~eLR#|8^`Z^?wLWxyS#>pRNiLJjD}%DQr?P`+t&r<7W3*-btw5iO}jOF~l;DN_;Yxo1?XKAvaydHLh{s&er0=Zxy=nDi{=j7p{-&UObwEE)6s`=-Q7e8IuoK?=BwZOH5PcW`s06{DW(s~C& zFa+sB5M+jal_3la=^zL}Nf{#GAOZ%$rU5ZF1&9%L5rTm+7)1*E)mHO;Y7c=5Udb}u zGySy+3@hUx;6+geN_Zpyi`T*g_*1lihO9G7YnBI($Ko=HUQrB+IWUtAB3g4k4hot4 zD5j9;8Y^V;_#9z8(Sr(%byX-d3WZ9i*wX-&8iaQ30EKD?Xt2ANG!R*BnB@Mh+)&| z=Y(+(B8JrXcxx9&IPri&g_D7+l}%cq+9e8 z=CXE5&pS76BCFJ2eoZ78BKHmz=4Z%q%&2Z139ao@U`SeGkj#pLl8Y>qbgPhtDRdv=jFJ=!W(mvS{AErXT!<)i7Np?W}_Aizr$hx1WaT- zGprua5o>#Q;&lwGUa^1p`lYD+(nf=eK_W7kE1N*X8UQ_Xqi^xbWiTybM<*f)7+t;$uN}) z>avU?p|by~fFn)fjk!YuUxr?LfJ@P=4cYHfwce91^?yB2GM>{vyY`mUUq$LYad>T4 z($7Vkc{{3q@iSQnkR=_8g4Nt@C60@a+vBr-TA_g*NSfCr8JnQQjPJj*VT9yey0oR? zNo|Bd*-ih>*(-LL)ai$rG!~XPGpy2R9A;Xb{#AF=QUBbZdsDpCuUS65m`BvO?r=~Y zTQnS&kZZo%cTH?h`JiIG_C%9u#ChLa?nqu9l3abRE3tIB?X8Q>F%?}>bMqP%T1H{v zxT;2chOzzC(kwn_iY=l?K-4!)h$-6D3Hj{IjPX;rO$3dklS$0V`kTJfWIdx!Rb?Vn zlgS#3W-&YQpI0zA46nk4~kO4uY| z4J?Zm7R^te_sPPImS_SYGx%HqnI&Y&0}Q1V7wF2C5wYq(^)qCAnos4jKl$bau`z;` zIvCQL++|d|t=k+AU7a_6qRu8VxvNmjv=%WIg**4JsZqSpKz<#1&@rOGFJU`wcT%&Z zXWDHg?$(+{+TjuL(3&oGXdm>AF7d!?i_Akl4JBRabt=4dJCG#A<+nHSNptnb>Kw_d zzutY_b#Kfb^CtUI@0F0*vs#+^nQpTb!B(F|q`Ii=yXwXV(*y?5F9rithjj5zSVPnS z>rR$}%d1^A(Ov5y$tAW(agdS!>?=5u!hn5zA*1-I#nK zC!E6w6Ec6lfXEO4sDMVLpcp_O83O2l{;~V-U?y@3KfhzZjqX|4LMZRKc*TRGD2Ggm=zXUAX2;SLr*;o^1`(jVh0B9dc{NNP76JNqo9 zFJqzFx8`>TQ%6o8%ekI^W2qiZyYO_r`(Dzj`sX{`uIS_j+W0-out`Y>JpE!QbaM-o z`J?uz_H0^vwR>?Qzb@zUjR330U-Fy_=5M-rzbREerruZ5dMELOeq%sa-P4v3y8pxA zRl98_{mkqp!X*t^M;!E_id>9CjvnMm>0u;TUWG0EXW zHG{2Rn7kVvuJgU?MnC%_NYeWyAocr*20M*{$DZNEk=rV@T0JIr1qBNx&a@j+_35Yb z7HOY6&@xawM_bXW{L;gmXQ_4rM(cR>9aREGcHg!{XVV5Jg~3p|u%H+5^Zl+ge<